Skip to content

Commit

Permalink
chore(doclint): support classes inheritance (#935)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
aslushnikov committed Oct 2, 2017
1 parent 8bcf550 commit 6c9a994
Show file tree
Hide file tree
Showing 33 changed files with 127 additions and 11 deletions.
35 changes: 34 additions & 1 deletion utils/doclint/check_public_api/JSBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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) {
Expand Down Expand Up @@ -140,19 +145,47 @@ 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>}>}
*/
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 };
};

20 changes: 20 additions & 0 deletions utils/doclint/check_public_api/test/js-builder-inheritance/foo.js
Original file line number Diff line number Diff line change
@@ -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'
};
Original file line number Diff line number Diff line change
@@ -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"
]
}
]
}
]
}
21 changes: 11 additions & 10 deletions utils/doclint/check_public_api/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down

0 comments on commit 6c9a994

Please sign in to comment.