prevent duplication when two parent classes have instance members with identical names (#613)

This commit is contained in:
Jeff Williams 2014-10-25 11:05:56 -07:00
parent 996c283733
commit e60fc3c717
3 changed files with 68 additions and 3 deletions

View File

@ -73,6 +73,7 @@ function getMembers(longname, docs) {
function getAdditions(doclets, docs, documented) {
var doop = require('jsdoc/util/doop');
var additionIndexes;
var additions = [];
var doc;
var parents;
@ -87,6 +88,8 @@ function getAdditions(doclets, docs, documented) {
doc = doclets[i];
parents = doc.augments;
if (parents && doc.kind === 'class') {
// reset the lookup table of added doclet indexes by longname
additionIndexes = {};
for (var j = 0, jj = parents.length; j < jj; j++) {
members = getMembers(parents[j], docs);
for (var k = 0, kk = members.length; k < kk; k++) {
@ -97,6 +100,8 @@ function getAdditions(doclets, docs, documented) {
}
member.inherited = true;
// TODO: this will fail on longnames like: MyClass#"quoted#Longname"
// and nested instance members like: MyClass#MyOtherClass#myMethod
member.memberof = doc.longname;
parts = member.longname.split('#');
parts[0] = doc.longname;
@ -105,7 +110,20 @@ function getAdditions(doclets, docs, documented) {
// add the ancestor's docs, unless the descendant both a) overrides the
// ancestor and b) documents the override
if ( !hasOwnProp.call(documented, member.longname) ) {
additions.push(member);
// We add only one doclet per longname. If you inherit from two classes that
// both use the same method name, you get docs for one method rather than
// two. Last one wins; if you write `@extends Class1 @extends Class2`, and
// both classes have the instance method `myMethod`, you get the `myMethod`
// docs from Class2.
if (typeof additionIndexes[member.longname] !== 'undefined') {
// replace the existing doclet
additions[additionIndexes[member.longname]] = member;
}
else {
// add the doclet to the array, and track its index
additions.push(member);
additionIndexes[member.longname] = additions.length - 1;
}
}
}
}

36
test/fixtures/augmentstag5.js vendored Normal file
View File

@ -0,0 +1,36 @@
/** @class */
'use strict';
function Base0() {}
Base0.prototype = /** @lends Base0# */ {
/** Description for {@link Base0#methodOfBaseCommon}. */
methodOfBaseCommon: function() {},
/** Description for {@link Base0#methodOfBase0}. */
methodOfBase0: function() {}
};
/** @class */
function Base1() {}
Base1.prototype = /** @lends Base1# */ {
/** Description for {@link Base1#methodOfBaseCommon}. */
methodOfBaseCommon: function() {},
/** Description for {@link Base1#methodOfBase1}. */
methodOfBase1: function() {}
};
/**
* @class
* @augments Base0
* @augments Base1
*/
function Class() {}
Class.prototype = Object.create(Base0.prototype);
Object.getOwnPropertyNames(Base1.prototype).forEach(function (prop) {
Object.defineProperty(Class.prototype, prop, Object.getOwnPropertyDescriptor(Base1.prototype, prop));
});

View File

@ -1,9 +1,12 @@
/*global describe: true, expect: true, it: true, jasmine: true */
describe("@augments tag", function() {
/*global describe, expect, it, jasmine */
'use strict';
describe('@augments tag', function() {
var docSet = jasmine.getDocSetFromFile('test/fixtures/augmentstag.js');
var docSet2 = jasmine.getDocSetFromFile('test/fixtures/augmentstag2.js');
var docSet3 = jasmine.getDocSetFromFile('test/fixtures/augmentstag3.js');
var docSet4 = jasmine.getDocSetFromFile('test/fixtures/augmentstag4.js');
var docSet5 = jasmine.getDocSetFromFile('test/fixtures/augmentstag5.js');
it('When a symbol has an @augments tag, the doclet has a augments property that includes that value.', function() {
var bar = docSet.getByLongname('Bar')[0];
@ -128,4 +131,12 @@
expect(derivedMethod1.undocumented).not.toBe(true);
expect(derivedMethod1.description).toBe(baseMethod1.description);
});
it('When a symbol inherits two methods that would both have the same longname, the last one wins', function() {
var base1CommonMethod = docSet5.getByLongname('Base1#methodOfBaseCommon')[0];
var classCommonMethod = docSet5.getByLongname('Class#methodOfBaseCommon');
expect(classCommonMethod.length).toBe(1);
expect(classCommonMethod[0].description).toBe(base1CommonMethod.description);
});
});