diff --git a/lib/jsdoc/tag/dictionary/definitions.js b/lib/jsdoc/tag/dictionary/definitions.js index 372c226f..672546e1 100644 --- a/lib/jsdoc/tag/dictionary/definitions.js +++ b/lib/jsdoc/tag/dictionary/definitions.js @@ -204,6 +204,42 @@ function firstWordOf(string) { } } +// Tags that JSDoc uses internally, and that must always be defined. +var internalTags = { + // Special separator tag indicating that multiple doclets should be generated for the same + // comment. Used internally (and by some JSDoc users, although it's not officially supported). + // In the following example, the parser will replace `//**` with an `@also` tag: + // /** + // * Foo. + // *//** + // * Foo with a param. + // * @param {string} bar + // */ + // function foo(bar) {} + also: { + onTagged: function() { + // let the parser handle it; we define the tag here to avoid "not a known tag" errors + } + }, + description: { + mustHaveValue: true, + synonyms: ['desc'] + }, + kind: { + mustHaveValue: true + }, + name: { + mustHaveValue: true + }, + undocumented: { + mustNotHaveValue: true, + onTagged: function(doclet) { + doclet.undocumented = true; + doclet.comment = ''; + } + } +}; + // Core JSDoc tags that are shared with other tag dictionaries. var baseTags = exports.baseTags = { @@ -233,21 +269,6 @@ var baseTags = exports.baseTags = { doclet.alias = tag.value; } }, - // Special separator tag indicating that multiple doclets should be generated for the same - // comment. Used internally (and by some JSDoc users, although it's not officially supported). - // In the following example, the parser will replace `//**` with an `@also` tag: - // /** - // * Foo. - // *//** - // * Foo with a param. - // * @param {string} bar - // */ - // function foo(bar) {} - also: { - onTagged: function() { - // let the parser handle it; we define the tag here to avoid "not a known tag" errors - } - }, async: { mustNotHaveValue: true, onTagged: function(doclet) { @@ -376,10 +397,6 @@ var baseTags = exports.baseTags = { doclet.deprecated = tag.value || true; } }, - description: { - mustHaveValue: true, - synonyms: ['desc'] - }, enum: { canHaveType: true, onTagged: function(doclet, tag) { @@ -514,9 +531,6 @@ var baseTags = exports.baseTags = { } } }, - kind: { - mustHaveValue: true - }, lends: { onTagged: function(doclet, tag) { doclet.alias = tag.value || jsdoc.name.LONGNAMES.GLOBAL; @@ -591,9 +605,6 @@ var baseTags = exports.baseTags = { setDocletTypeToValueType(doclet, tag); } }, - name: { - mustHaveValue: true - }, namespace: { canHaveType: true, onTagged: function(doclet, tag) { @@ -795,13 +806,6 @@ var baseTags = exports.baseTags = { }, synonyms: ['callback'] }, - undocumented: { - mustNotHaveValue: true, - onTagged: function(doclet) { - doclet.undocumented = true; - doclet.comment = ''; - } - }, variation: { mustHaveValue: true, onTagged: function(doclet, tag) { @@ -831,6 +835,8 @@ var baseTags = exports.baseTags = { } }; +baseTags = _.extend(baseTags, internalTags); + // Tag dictionary for JSDoc. exports.jsdocTags = baseTags; @@ -856,6 +862,10 @@ exports.closureTags = { onTagged: ignore }, enum: cloneTagDef(baseTags.enum), + // Closure Compiler only + export: { + onTagged: ignore + }, extends: cloneTagDef(baseTags.augments), final: cloneTagDef(baseTags.readonly), implements: cloneTagDef(baseTags.implements), @@ -864,12 +874,8 @@ exports.closureTags = { canHaveName: false, mustNotHaveValue: true }), - // not a Closure Compiler tag, but JSDoc uses this internally - kind: cloneTagDef(baseTags.kind), lends: cloneTagDef(baseTags.lends), license: cloneTagDef(baseTags.license), - // not a Closure Compiler tag, but JSDoc uses this internally - name: cloneTagDef(baseTags.name), // Closure Compiler only override: { mustNotHaveValue: true, @@ -970,10 +976,10 @@ exports.defineTags = function(dictionary, tagDefinitions) { return; } - addTagDefinitions(dictionary, tagDefs); + addTagDefinitions(dictionary, _.extend(tagDefs, internalTags)); }); } else { - addTagDefinitions(dictionary, tagDefinitions); + addTagDefinitions(dictionary, _.extend(tagDefinitions, internalTags)); } }; diff --git a/test/fixtures/exporttag.js b/test/fixtures/exporttag.js new file mode 100644 index 00000000..e4503e14 --- /dev/null +++ b/test/fixtures/exporttag.js @@ -0,0 +1,14 @@ +/** + * My class. + * + * @constructor + * @export + */ +function MyClass() {} + +/** + * My public method. + * + * @export + */ +MyClass.prototype.myPublicMethod = function() {}; diff --git a/test/specs/tags/exporttag.js b/test/specs/tags/exporttag.js new file mode 100644 index 00000000..a554d290 --- /dev/null +++ b/test/specs/tags/exporttag.js @@ -0,0 +1,42 @@ +'use strict'; + +describe('@export tag', function() { + var env = require('jsdoc/env'); + var logger = require('jsdoc/util/logger'); + + var allowUnknownTags = Boolean(env.conf.tags.allowUnknownTags); + + beforeEach(function() { + env.conf.tags.allowUnknownTags = false; + spyOn(logger, 'error'); + }); + + afterEach(function() { + jasmine.restoreTagDictionary(); + env.conf.tags.allowUnknownTags = allowUnknownTags; + }); + + describe('JSDoc tags', function() { + beforeEach(function() { + jasmine.replaceTagDictionary('jsdoc'); + }); + + it('should not recognize the @export tag', function() { + jasmine.getDocSetFromFile('test/fixtures/exporttag.js'); + + expect(logger.error).toHaveBeenCalled(); + }); + }); + + describe('Closure Compiler tags', function() { + beforeEach(function() { + jasmine.replaceTagDictionary('closure'); + }); + + it('should recognize the @export tag', function() { + jasmine.getDocSetFromFile('test/fixtures/exporttag.js'); + + expect(logger.error).not.toHaveBeenCalled(); + }); + }); +});