diff --git a/lib/jsdoc/augment.js b/lib/jsdoc/augment.js index 7207ef0b..d195a3e5 100644 --- a/lib/jsdoc/augment.js +++ b/lib/jsdoc/augment.js @@ -145,40 +145,40 @@ exports.addInherited = function(docs) { exports.addImplemented = function(docs) { var docMap = {}; - var interfaces = []; + var interfaces = {}; var implemented = {}; - var propertyInfo = {}; + var memberInfo = {}; docs.forEach(function(doc) { - if (!hasOwnProp.call(docMap, doc.memberof)) { - docMap[doc.memberof] = []; + var memberof = doc.memberof || doc.name; + + if (!hasOwnProp.call(docMap, memberof)) { + docMap[memberof] = []; } - docMap[doc.memberof].push(doc); + docMap[memberof].push(doc); if (doc.kind === 'interface') { - interfaces.push(doc); - } else if (doc.implements && doc.implements.length) { + interfaces[doc.longname] = doc; + } + else if (doc.implements && doc.implements.length) { if (!hasOwnProp.call(implemented, doc.memberof)) { - implemented[doc.memberof] = []; + implemented[memberof] = []; } - implemented[doc.memberof].push(doc); + implemented[memberof].push(doc); } }); - // create an array of interface properties/methods, plus a hash of the doclet for each one - interfaces.forEach(function(inf) { - if (hasOwnProp.call(docMap, inf.name)) { - docMap[inf.name].forEach(function(obj) { - var members = propertyInfo[obj.memberof]; - if (!members) { - members = propertyInfo[obj.memberof] = { - props: [], - info: {} - }; - } + // create an dictionary of interface doclets + Object.keys(interfaces).forEach(function(ifaceName) { + var iface = interfaces[ifaceName]; + if (hasOwnProp.call(docMap, iface.name)) { + docMap[iface.name].forEach(function(doc) { + var members = memberInfo[doc.memberof]; - members.props.push(obj.name); - members.info[obj.name] = obj; + if (!members) { + members = memberInfo[doc.memberof] = {}; + } + members[doc.name] = doc; }); } }); @@ -187,20 +187,46 @@ exports.addImplemented = function(docs) { // implemented classes namespace. var owner = implemented[key]; - owner.forEach(function(cls) { + owner.forEach(function(klass) { // class's interfaces - cls.implements.forEach(function(impl) { - var implProps = propertyInfo[impl]; - var props = docMap[cls.longname] || []; + klass.implements.forEach(function(impl) { + var interfaceMember; + var interfaceMembers = memberInfo[impl]; + var member; + var members; - for (var i = 0, len = props.length; i < len; i++) { - var prop = props[i]; + // mark the interface as being implemented by the class + if (hasOwnProp.call(interfaces, impl)) { + interfaces[impl].implementations = interfaces[impl].implementations || []; + interfaces[impl].implementations.push(klass.longname); + } - // mark implemented properties by checking the implProps array for each name - if (implProps && implProps.props.indexOf(prop.name) > -1) { - prop.implemented = true; - prop.implementProp = implProps.info[prop.name].longname; + // if the interface has no members, skip to the next owner + if (!interfaceMembers) { + return; + } + + if (!hasOwnProp.call(docMap, klass.longname)) { + docMap[klass.longname] = []; + } + members = docMap[klass.longname]; + + for (var i = 0, len = members.length; i < len; i++) { + member = members[i]; + interfaceMember = interfaceMembers && interfaceMembers[member.name]; + + // if we didn't find the member name in the interface, skip to the next member + if (!interfaceMember) { + continue; } + + // mark members that implement an interface + member.implements = member.implements || []; + member.implements.push(interfaceMember.longname); + + // mark interface members that the symbol implements + interfaceMember.implementations = interfaceMember.implementations || []; + interfaceMember.implementations.push(member.longname); } }); }); diff --git a/lib/jsdoc/schema.js b/lib/jsdoc/schema.js index 73e10852..c9f03ec1 100644 --- a/lib/jsdoc/schema.js +++ b/lib/jsdoc/schema.js @@ -334,17 +334,19 @@ var DOCLET_SCHEMA = exports.DOCLET_SCHEMA = { type: BOOLEAN, optional: true }, + implementations: { + type: ARRAY, + optional: true, + items: { + type: STRING + } + }, implements: { type: ARRAY, - optional: true - }, - implemented: { - type: BOOLEAN, - optional: true - }, - implementProp: { - type: STRING, - optional: true + optional: true, + items: { + type: STRING + } }, inherited: { type: BOOLEAN, diff --git a/templates/default/static/styles/jsdoc-default.css b/templates/default/static/styles/jsdoc-default.css index 124ef6c7..7813ef82 100644 --- a/templates/default/static/styles/jsdoc-default.css +++ b/templates/default/static/styles/jsdoc-default.css @@ -195,8 +195,8 @@ h6 } .details { margin-top: 14px; border-left: 2px solid #DDD; } -.details dt { width:100px; float:left; padding-left: 10px; padding-top: 6px; } -.details dd { margin-left: 50px; } +.details dt { width:120px; float:left; padding-left: 10px; padding-top: 6px; } +.details dd { margin-left: 70px; } .details ul { margin: 0; } .details ul { list-style-type: none; } .details li { margin-left: 30px; padding-top: 6px; } diff --git a/templates/default/tmpl/container.tmpl b/templates/default/tmpl/container.tmpl index 63dfe47f..376ed29f 100644 --- a/templates/default/tmpl/container.tmpl +++ b/templates/default/tmpl/container.tmpl @@ -80,48 +80,6 @@ - -

Implements

- - - - - -

Implementations

- - - - - -
Implementes:
-
+ +
Implementations:
+
+ + + +
Implements:
+
diff --git a/test/specs/tags/implementstag.js b/test/specs/tags/implementstag.js index 6691b17c..0a584aa9 100644 --- a/test/specs/tags/implementstag.js +++ b/test/specs/tags/implementstag.js @@ -12,12 +12,13 @@ describe('@implements tag', function() { it('MyTester has an "implements" array', function() { expect(Array.isArray(myTester.implements)).toBe(true); expect(myTester.implements.length).toBe(1); - expect(myTester.implements[0]).toEqual('ITester'); + expect(myTester.implements[0]).toBe('ITester'); }); - it('beforeEach has "implemented" and "implementProp" property', function() { - expect(beforeEachMethod.implemented).toBeDefined(); - expect(beforeEachMethod.implementProp).toBeDefined(); + it('beforeEach has an "implements" array', function() { + expect(Array.isArray(beforeEachMethod.implements)).toBe(true); + expect(beforeEachMethod.implements.length).toBe(1); + expect(beforeEachMethod.implements[0]).toBe('ITester#beforeEach'); }); it('MyWorker\'s process() method does not implement an interface', function() {