mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
chore(doclint): support classes inheritance (#935)
This patch: - gives meaningful names to doclint tests - supports classes inheritance in documentation linter. When class A extends class B, all methods of class B are added to documentation of class A. This is a prerequisite for Object Handles: ElementHandle will be extending ObjectHandle. References #382
This commit is contained in:
parent
8bcf550bb6
commit
6c9a99477b
@ -21,6 +21,8 @@ const Documentation = require('./Documentation');
|
||||
class JSOutline {
|
||||
constructor(text) {
|
||||
this.classes = [];
|
||||
/** @type {!Map<string, string>} */
|
||||
this.inheritance = new Map();
|
||||
this.errors = [];
|
||||
this._eventsByClassName = new Map();
|
||||
this._currentClassName = null;
|
||||
@ -44,6 +46,9 @@ class JSOutline {
|
||||
_onClassDeclaration(node) {
|
||||
this._flushClassIfNeeded();
|
||||
this._currentClassName = this._extractText(node.id);
|
||||
const superClass = this._extractText(node.superClass);
|
||||
if (superClass)
|
||||
this.inheritance.set(this._currentClassName, superClass);
|
||||
}
|
||||
|
||||
_onMethodDefinition(node) {
|
||||
@ -140,6 +145,31 @@ class JSOutline {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!Array<!Documentation.Class>} classes
|
||||
* @param {!Map<string, string>} inheritance
|
||||
* @return {!Array<!Documentation.Class>}
|
||||
*/
|
||||
function recreateClassesWithInheritance(classes, inheritance) {
|
||||
const classesByName = new Map(classes.map(cls => [cls.name, cls]));
|
||||
return classes.map(cls => {
|
||||
const membersMap = new Map();
|
||||
for (let wp = cls; wp; wp = classesByName.get(inheritance.get(wp.name))) {
|
||||
for (const member of wp.membersArray) {
|
||||
// Member was overridden.
|
||||
const memberId = member.type + ':' + member.name;
|
||||
if (membersMap.has(memberId))
|
||||
continue;
|
||||
// Do not inherit constructors
|
||||
if (wp !== cls && member.name === 'constructor' && member.type === 'method')
|
||||
continue;
|
||||
membersMap.set(memberId, member);
|
||||
}
|
||||
}
|
||||
return new Documentation.Class(cls.name, Array.from(membersMap.values()));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!Array<!Source>} sources
|
||||
* @return {!Promise<{documentation: !Documentation, errors: !Array<string>}>}
|
||||
@ -147,12 +177,15 @@ class JSOutline {
|
||||
module.exports = async function(sources) {
|
||||
const classes = [];
|
||||
const errors = [];
|
||||
const inheritance = new Map();
|
||||
for (const source of sources) {
|
||||
const outline = new JSOutline(source.text());
|
||||
classes.push(...outline.classes);
|
||||
errors.push(...outline.errors);
|
||||
for (const entry of outline.inheritance)
|
||||
inheritance.set(entry[0], entry[1]);
|
||||
}
|
||||
const documentation = new Documentation(classes);
|
||||
const documentation = new Documentation(recreateClassesWithInheritance(classes, inheritance));
|
||||
return { documentation, errors };
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,20 @@
|
||||
class A {
|
||||
constructor() {
|
||||
}
|
||||
|
||||
foo(a) {
|
||||
}
|
||||
|
||||
bar() {
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
bar(override) {
|
||||
}
|
||||
}
|
||||
|
||||
B.Events = {
|
||||
// Event with the same name as a super class method.
|
||||
foo: 'foo'
|
||||
};
|
@ -0,0 +1,62 @@
|
||||
{
|
||||
"classes": [
|
||||
{
|
||||
"name": "A",
|
||||
"members": [
|
||||
{
|
||||
"name": "constructor",
|
||||
"type": "method",
|
||||
"hasReturn": false,
|
||||
"async": false,
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"name": "foo",
|
||||
"type": "method",
|
||||
"hasReturn": false,
|
||||
"async": false,
|
||||
"args": [
|
||||
"a"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "bar",
|
||||
"type": "method",
|
||||
"hasReturn": false,
|
||||
"async": false,
|
||||
"args": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "B",
|
||||
"members": [
|
||||
{
|
||||
"name": "bar",
|
||||
"type": "method",
|
||||
"hasReturn": false,
|
||||
"async": false,
|
||||
"args": [
|
||||
"override"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "foo",
|
||||
"type": "event",
|
||||
"hasReturn": false,
|
||||
"async": false,
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"name": "foo",
|
||||
"type": "method",
|
||||
"hasReturn": false,
|
||||
"async": false,
|
||||
"args": [
|
||||
"a"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -47,16 +47,17 @@ afterAll(SX(async function() {
|
||||
}));
|
||||
|
||||
describe('checkPublicAPI', function() {
|
||||
it('01-class-errors', SX(testLint));
|
||||
it('02-method-errors', SX(testLint));
|
||||
it('03-property-errors', SX(testLint));
|
||||
it('04-bad-arguments', SX(testLint));
|
||||
it('05-event-errors', SX(testLint));
|
||||
it('06-duplicates', SX(testLint));
|
||||
it('07-sorting', SX(testLint));
|
||||
it('08-return', SX(testLint));
|
||||
it('09-js-builder', SX(testJSBuilder));
|
||||
it('10-md-builder', SX(testMDBuilder));
|
||||
it('diff-classes', SX(testLint));
|
||||
it('diff-methods', SX(testLint));
|
||||
it('diff-properties', SX(testLint));
|
||||
it('diff-arguments', SX(testLint));
|
||||
it('diff-events', SX(testLint));
|
||||
it('check-duplicates', SX(testLint));
|
||||
it('check-sorting', SX(testLint));
|
||||
it('check-returns', SX(testLint));
|
||||
it('js-builder-common', SX(testJSBuilder));
|
||||
it('js-builder-inheritance', SX(testJSBuilder));
|
||||
it('md-builder-common', SX(testMDBuilder));
|
||||
});
|
||||
|
||||
async function testLint() {
|
||||
|
Loading…
Reference in New Issue
Block a user