support the export tag (Closure Compiler only) (#605)

This commit is contained in:
Jeff Williams 2017-07-16 16:47:20 -07:00
parent 2e739594b8
commit d06ba2788a
3 changed files with 100 additions and 38 deletions

View File

@ -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. // Core JSDoc tags that are shared with other tag dictionaries.
var baseTags = exports.baseTags = { var baseTags = exports.baseTags = {
@ -233,21 +269,6 @@ var baseTags = exports.baseTags = {
doclet.alias = tag.value; 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: { async: {
mustNotHaveValue: true, mustNotHaveValue: true,
onTagged: function(doclet) { onTagged: function(doclet) {
@ -376,10 +397,6 @@ var baseTags = exports.baseTags = {
doclet.deprecated = tag.value || true; doclet.deprecated = tag.value || true;
} }
}, },
description: {
mustHaveValue: true,
synonyms: ['desc']
},
enum: { enum: {
canHaveType: true, canHaveType: true,
onTagged: function(doclet, tag) { onTagged: function(doclet, tag) {
@ -514,9 +531,6 @@ var baseTags = exports.baseTags = {
} }
} }
}, },
kind: {
mustHaveValue: true
},
lends: { lends: {
onTagged: function(doclet, tag) { onTagged: function(doclet, tag) {
doclet.alias = tag.value || jsdoc.name.LONGNAMES.GLOBAL; doclet.alias = tag.value || jsdoc.name.LONGNAMES.GLOBAL;
@ -591,9 +605,6 @@ var baseTags = exports.baseTags = {
setDocletTypeToValueType(doclet, tag); setDocletTypeToValueType(doclet, tag);
} }
}, },
name: {
mustHaveValue: true
},
namespace: { namespace: {
canHaveType: true, canHaveType: true,
onTagged: function(doclet, tag) { onTagged: function(doclet, tag) {
@ -795,13 +806,6 @@ var baseTags = exports.baseTags = {
}, },
synonyms: ['callback'] synonyms: ['callback']
}, },
undocumented: {
mustNotHaveValue: true,
onTagged: function(doclet) {
doclet.undocumented = true;
doclet.comment = '';
}
},
variation: { variation: {
mustHaveValue: true, mustHaveValue: true,
onTagged: function(doclet, tag) { onTagged: function(doclet, tag) {
@ -831,6 +835,8 @@ var baseTags = exports.baseTags = {
} }
}; };
baseTags = _.extend(baseTags, internalTags);
// Tag dictionary for JSDoc. // Tag dictionary for JSDoc.
exports.jsdocTags = baseTags; exports.jsdocTags = baseTags;
@ -856,6 +862,10 @@ exports.closureTags = {
onTagged: ignore onTagged: ignore
}, },
enum: cloneTagDef(baseTags.enum), enum: cloneTagDef(baseTags.enum),
// Closure Compiler only
export: {
onTagged: ignore
},
extends: cloneTagDef(baseTags.augments), extends: cloneTagDef(baseTags.augments),
final: cloneTagDef(baseTags.readonly), final: cloneTagDef(baseTags.readonly),
implements: cloneTagDef(baseTags.implements), implements: cloneTagDef(baseTags.implements),
@ -864,12 +874,8 @@ exports.closureTags = {
canHaveName: false, canHaveName: false,
mustNotHaveValue: true mustNotHaveValue: true
}), }),
// not a Closure Compiler tag, but JSDoc uses this internally
kind: cloneTagDef(baseTags.kind),
lends: cloneTagDef(baseTags.lends), lends: cloneTagDef(baseTags.lends),
license: cloneTagDef(baseTags.license), license: cloneTagDef(baseTags.license),
// not a Closure Compiler tag, but JSDoc uses this internally
name: cloneTagDef(baseTags.name),
// Closure Compiler only // Closure Compiler only
override: { override: {
mustNotHaveValue: true, mustNotHaveValue: true,
@ -970,10 +976,10 @@ exports.defineTags = function(dictionary, tagDefinitions) {
return; return;
} }
addTagDefinitions(dictionary, tagDefs); addTagDefinitions(dictionary, _.extend(tagDefs, internalTags));
}); });
} }
else { else {
addTagDefinitions(dictionary, tagDefinitions); addTagDefinitions(dictionary, _.extend(tagDefinitions, internalTags));
} }
}; };

14
test/fixtures/exporttag.js vendored Normal file
View File

@ -0,0 +1,14 @@
/**
* My class.
*
* @constructor
* @export
*/
function MyClass() {}
/**
* My public method.
*
* @export
*/
MyClass.prototype.myPublicMethod = function() {};

View File

@ -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();
});
});
});