From e3f6d5a3e5c1e656a0e780fdffc6eac6a866a3e1 Mon Sep 17 00:00:00 2001 From: Michael Mathews Date: Thu, 1 Jul 2010 22:54:50 +0100 Subject: [PATCH] Added support for @property tag, with tests. --- modules/jsdoc/doclet.js | 44 ++++++++++--------- test/runall.js | 1 + test/tests/12_tag_property.js | 83 +++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 20 deletions(-) create mode 100644 test/tests/12_tag_property.js diff --git a/modules/jsdoc/doclet.js b/modules/jsdoc/doclet.js index 7bad4223..cd58e1e1 100644 --- a/modules/jsdoc/doclet.js +++ b/modules/jsdoc/doclet.js @@ -217,9 +217,9 @@ } // other tags that can provide the memberof - var memberofs = {methodof: 'method', eventof: 'event'}; + var memberofs = {methodof: 'method', propertyof: 'property', eventof: 'event'}; // other tags that can provide the symbol name - var nameables = ['constructor', 'const', 'module', 'event', 'namespace', 'method', 'member', 'function', 'variable', 'enum']; + var nameables = ['constructor', 'const', 'module', 'event', 'namespace', 'method', 'property', 'function', 'variable', 'enum']; /** Expand some shortcut tags. Modifies the tags argument in-place. @@ -236,8 +236,7 @@ memberof = '', taggedMemberof = ''; - var i = tags.length; - while(i--) { + for (var i = 0, leni = tags.length; i < leni; i++) { if (tags[i].name === 'private') { tags[tags.length] = parse_tag.fromTagText('access private'); @@ -274,26 +273,31 @@ } if ( nameables.indexOf(tags[i].name) > -1 ) { - if (tags[i].text) { - if (name && name !== tags[i].text) { - throw new DocTagConflictError('Conflicting names in documentation: '+name+', '+tags[i].text); + if (tags[i].name === 'property' && (isa === 'constructor')) { + // for backwards compatability we ignore a @property in a doclet after a @constructor + } + else { + if (tags[i].text) { + if (name && name !== tags[i].text) { + throw new DocTagConflictError('Conflicting names in documentation: '+name+', '+tags[i].text); + } + name = tags[i].text; } - name = tags[i].text; - } - if (tags[i].pdesc) { - tags[tags.length] = parse_tag.fromTagText('desc ' + tags[i].pdesc); - } + if (tags[i].pdesc) { + tags[tags.length] = parse_tag.fromTagText('desc ' + tags[i].pdesc); + } - if (tags[i].type) { - tags[tags.length] = parse_tag.fromTagText('type ' + tags[i].type.join('|')); - } + if (tags[i].type) { + tags[tags.length] = parse_tag.fromTagText('type ' + tags[i].type.join('|')); + } - if (isa && isa !== tags[i].name) { - throw new DocTagConflictError('Symbol has too many denominations, cannot be both: ' + isa + ' and ' + tags[i].name); + if (isa && isa !== tags[i].name) { + throw new DocTagConflictError('Symbol has too many denominations, cannot be both: ' + isa + ' and ' + tags[i].name); + } + isa = tags[i].name; + if (isa === 'const') { isa = 'property'; } // an exception to the namebale rule } - isa = tags[i].name; - if (isa === 'const') { isa = 'member'; } // an exception to the namebale rule } if ( memberofs.hasOwnProperty(tags[i].name) ) { @@ -341,7 +345,7 @@ if ( doclet.hasTag('const')) { if (!doclet.hasTag('isa')) { - doclet.tags[doclet.tags.length] = parse_tag.fromTagText('isa member'); + doclet.tags[doclet.tags.length] = parse_tag.fromTagText('isa property'); } if (!doclet.hasTag('readonly') && !doclet.hasTag('const')) { diff --git a/test/runall.js b/test/runall.js index 1bba2528..5f6104b4 100644 --- a/test/runall.js +++ b/test/runall.js @@ -7,6 +7,7 @@ load(BASEDIR + '/test/tests/06_jsdoc_tag.js'); load(BASEDIR + '/test/tests/10_tag_constructor.js'); load(BASEDIR + '/test/tests/11_tag_namespace.js'); +load(BASEDIR + '/test/tests/12_tag_property.js'); // see http://visionmedia.github.com/jspec/ JSpec.run({ diff --git a/test/tests/12_tag_property.js b/test/tests/12_tag_property.js new file mode 100644 index 00000000..976965ba --- /dev/null +++ b/test/tests/12_tag_property.js @@ -0,0 +1,83 @@ +(function() { + var jsdoc, + doclets; + + JSpec.describe('@property', function() { + + before_each(function() { + // docsets can only be created by parsers + jsdoc = { + tag: require('jsdoc/tag'), + parser: require('jsdoc/parser') + }; + jsdoc.parser.parseFiles(BASEDIR + 'test/tests/12_tag_property.js'); + doclets = jsdoc.parser.result; + + }); + + describe('A doclet with a named property tag attached to a namespace', function() { + it('should have an `isa` property set to "property"', function() { + var doclet = doclets[2].toObject(); + expect(doclet).to(have_property, 'isa'); + expect(doclet.isa).to(eql, 'property'); + }); + + it('should have a `name` property set to the given name"', function() { + var doclet = doclets[2].toObject(); + expect(doclet).to(have_property, 'name'); + expect(doclet.name).to(eql, 'fah'); + }); + + it('should have a `memberof` property set to the parent object name', function() { + var doclet = doclets[2].toObject(); + expect(doclet).to(have_property, 'memberof'); + expect(doclet.memberof).to(eql, 'foo'); + }); + }); + + describe('A doclet with a named property tag attached to a constructor', function() { + it('should have an `isa` property set to "property"', function() { + var doclet = doclets[3].toObject(); + expect(doclet).to(have_property, 'isa'); + expect(doclet.isa).to(eql, 'property'); + }); + + it('should have a `name` property set to the given name"', function() { + var doclet = doclets[3].toObject(); + expect(doclet).to(have_property, 'name'); + expect(doclet.name).to(eql, 'bah'); + }); + + it('should have a `memberof` property set to the parent object name', function() { + var doclet = doclets[3].toObject(); + expect(doclet).to(have_property, 'memberof'); + expect(doclet.memberof).to(eql, 'bar'); + }); + }); + + describe('A doclet with a named property tag after to a constructor tag', function() { + it('should be a constructor', function() { + var doclet = doclets[4].toObject(); + expect(doclet).to(have_property, 'isa'); + expect(doclet.isa).to(eql, 'constructor'); + }); + }); + + }); +})(); + +(function testarea() { + + /** @namespace foo */ + + /** @constructor bar */ + + /** @property foo.fah */ + + /** @property bar.bah */ + + /** @constructor Zub + @property {string} zip + */ + +})(); \ No newline at end of file