clean up constants exported by jsdoc/name

This commit is contained in:
Jeff Williams 2014-07-03 12:35:56 -07:00
parent abfa24578c
commit dcca9a4714
8 changed files with 124 additions and 62 deletions

View File

@ -217,7 +217,7 @@ Doclet.prototype.addTag = function(title, text) {
}; };
function removeGlobal(longname) { function removeGlobal(longname) {
var globalRegexp = new RegExp('^' + jsdoc.name.GLOBAL_LONGNAME + '\\.?'); var globalRegexp = new RegExp('^' + jsdoc.name.LONGNAMES.GLOBAL + '\\.?');
return longname.replace(globalRegexp, ''); return longname.replace(globalRegexp, '');
} }
@ -233,7 +233,7 @@ Doclet.prototype.setMemberof = function(sid) {
* @type string * @type string
*/ */
this.memberof = removeGlobal(sid) this.memberof = removeGlobal(sid)
.replace(/\.prototype/g, jsdoc.name.INSTANCE); .replace(/\.prototype/g, jsdoc.name.SCOPE.PUNC.INSTANCE);
}; };
/** /**
@ -270,22 +270,22 @@ function getFilepath(doclet) {
/** /**
* Set the doclet's `scope` property. Must correspond to a scope name that is defined in * Set the doclet's `scope` property. Must correspond to a scope name that is defined in
* {@link module:jsdoc/name.SCOPE_NAMES}. * {@link module:jsdoc/name.SCOPE.NAMES}.
* *
* @param {module:jsdoc/name.SCOPE_NAMES} scope - The scope for the doclet relative to the symbol's * @param {module:jsdoc/name.SCOPE.NAMES} scope - The scope for the doclet relative to the symbol's
* parent. * parent.
* @throws {Error} If the scope name is not recognized. * @throws {Error} If the scope name is not recognized.
*/ */
Doclet.prototype.setScope = function(scope) { Doclet.prototype.setScope = function(scope) {
var errorMessage; var errorMessage;
var filepath; var filepath;
var scopeNames = Object.keys(jsdoc.name.SCOPE_NAMES); var scopeNames = _.values(jsdoc.name.SCOPE.NAMES);
if (scopeNames.indexOf(scope) === -1) { if (scopeNames.indexOf(scope) === -1) {
filepath = getFilepath(this); filepath = getFilepath(this);
errorMessage = util.format('The scope name "%s" is not recognized. Use one of the names ' + errorMessage = util.format('The scope name "%s" is not recognized. Use one of the ' +
'defined in module:jsdoc/name.SCOPE_NAMES.', scope); 'following values: %j', scope, scopeNames);
if (filepath) { if (filepath) {
errorMessage += util.format(' (Source file: %s)', filepath); errorMessage += util.format(' (Source file: %s)', filepath);
} }

View File

@ -8,30 +8,64 @@
var _ = require('underscore'); var _ = require('underscore');
// Longname used for doclets whose actual longname cannot be identified. /**
var ANONYMOUS_LONGNAME = exports.ANONYMOUS_LONGNAME = '<anonymous>'; * Longnames that have a special meaning in JSDoc.
// Longname used for doclets in global scope. *
var GLOBAL_LONGNAME = exports.GLOBAL_LONGNAME = '<global>'; * @enum {string}
var INNER = exports.INNER = '~'; * @static
var INSTANCE = exports.INSTANCE = '#'; * @memberof module:jsdoc/name
var MODULE_PREFIX = exports.MODULE_PREFIX = 'module:'; */
// Scope identifiers. var LONGNAMES = exports.LONGNAMES = {
var SCOPE_NAMES = exports.SCOPE_NAMES = { /** Longname used for doclets that do not have a longname, such as anonymous functions. */
global: 'global', ANONYMOUS: '<anonymous>',
inner: 'inner', /** Longname that represents global scope. */
instance: 'instance', GLOBAL: '<global>'
'static': 'static'
}; };
var STATIC = exports.STATIC = '.';
// TODO: Consider removing this rather than completing the list. In theory, any new tag can act as
// a namespace by setting its `isNamespace` attribute to `true`.
/**
* Namespaces that can be applied to a longname.
*
* @enum {string}
* @static
* @memberof module:jsdoc/name
*/
var NAMESPACES = exports.NAMESPACES = {
MODULE: 'module:'
};
/**
* Names and punctuation marks that identify doclet scopes.
*
* @enum {string}
* @static
* @memberof module:jsdoc/name
*/
var SCOPE = exports.SCOPE = {
NAMES: {
GLOBAL: 'global',
INNER: 'inner',
INSTANCE: 'instance',
STATIC: 'static'
},
PUNC: {
INNER: '~',
INSTANCE: '#',
STATIC: '.'
}
};
// For backwards compatibility, this enum must use lower-case keys
var scopeToPunc = exports.scopeToPunc = { var scopeToPunc = exports.scopeToPunc = {
'inner': INNER, 'inner': SCOPE.PUNC.INNER,
'instance': INSTANCE, 'instance': SCOPE.PUNC.INSTANCE,
'static': STATIC 'static': SCOPE.PUNC.STATIC
}; };
var puncToScope = exports.puncToScope = _.invert(scopeToPunc); var puncToScope = exports.puncToScope = _.invert(scopeToPunc);
var DEFAULT_SCOPE = SCOPE_NAMES.static; var DEFAULT_SCOPE = SCOPE.NAMES.STATIC;
var REGEXP_SCOPE_PUNC = '([' + INNER + INSTANCE + STATIC + '])'; var REGEXP_SCOPE_PUNC = '([' + _.values(SCOPE.PUNC) + '])';
var REGEXP_LEADING_SCOPE = new RegExp('^' + REGEXP_SCOPE_PUNC); var REGEXP_LEADING_SCOPE = new RegExp('^' + REGEXP_SCOPE_PUNC);
var REGEXP_TRAILING_SCOPE = new RegExp(REGEXP_SCOPE_PUNC + '$'); var REGEXP_TRAILING_SCOPE = new RegExp(REGEXP_SCOPE_PUNC + '$');
@ -42,7 +76,7 @@ function nameIsLongname(name, memberof) {
} }
function prototypeToPunc(name) { function prototypeToPunc(name) {
return name.replace(/(?:^|\.)prototype\.?/g, INSTANCE); return name.replace(/(?:^|\.)prototype\.?/g, SCOPE.PUNC.INSTANCE);
} }
/** /**
@ -66,7 +100,7 @@ exports.resolve = function(doclet) {
// member of a var in an outer scope? // member of a var in an outer scope?
if (name && !memberof && doclet.meta.code && doclet.meta.code.funcscope) { if (name && !memberof && doclet.meta.code && doclet.meta.code.funcscope) {
name = doclet.longname = doclet.meta.code.funcscope + INNER + name; name = doclet.longname = doclet.meta.code.funcscope + SCOPE.PUNC.INNER + name;
} }
if (memberof || doclet.forceMemberof) { // @memberof tag given if (memberof || doclet.forceMemberof) { // @memberof tag given
@ -78,7 +112,7 @@ exports.resolve = function(doclet) {
} }
// the name and memberof are identical and refer to a module, // the name and memberof are identical and refer to a module,
// like @name module:foo, @memberof module:foo (probably a member like 'var exports') // like @name module:foo, @memberof module:foo (probably a member like 'var exports')
else if (name && name === memberof && name.indexOf(MODULE_PREFIX) === 0) { else if (name && name === memberof && name.indexOf(NAMESPACES.MODULE) === 0) {
about = exports.shorten(name, (doclet.forceMemberof ? memberof : undefined)); about = exports.shorten(name, (doclet.forceMemberof ? memberof : undefined));
} }
// the name and memberof are identical, like @name foo, @memberof foo // the name and memberof are identical, like @name foo, @memberof foo
@ -117,7 +151,7 @@ exports.resolve = function(doclet) {
delete doclet.memberof; delete doclet.memberof;
} }
else if (about.scope) { else if (about.scope) {
if (about.memberof === GLOBAL_LONGNAME) { // via @memberof <global> ? if (about.memberof === LONGNAMES.GLOBAL) { // via @memberof <global> ?
doclet.scope = 'global'; doclet.scope = 'global';
} }
else { else {

View File

@ -10,7 +10,7 @@ var uid = 100000000;
// TODO: docs // TODO: docs
// TODO: currently unused // TODO: currently unused
var GLOBAL_NODE_ID = exports.GLOBAL_NODE_ID = require('jsdoc/name').GLOBAL_LONGNAME; var GLOBAL_NODE_ID = exports.GLOBAL_NODE_ID = require('jsdoc/name').LONGNAMES.GLOBAL;
/** /**
* Check whether an AST node represents a function. * Check whether an AST node represents a function.

View File

@ -269,7 +269,7 @@ Parser.prototype.addDocletRef = function(e) {
(node.type === Syntax.FunctionDeclaration || node.type === Syntax.FunctionExpression) && (node.type === Syntax.FunctionDeclaration || node.type === Syntax.FunctionExpression) &&
!this.refs[node.nodeId] ) { !this.refs[node.nodeId] ) {
this.refs[node.nodeId] = { this.refs[node.nodeId] = {
longname: jsdoc.name.ANONYMOUS_LONGNAME, longname: jsdoc.name.LONGNAMES.ANONYMOUS,
meta: { meta: {
code: e.code code: e.code
} }
@ -323,10 +323,10 @@ Parser.prototype.astnodeToMemberof = function(node) {
doclet = this._getDoclet(node.enclosingScope.nodeId); doclet = this._getDoclet(node.enclosingScope.nodeId);
if (!doclet) { if (!doclet) {
result = jsdoc.name.ANONYMOUS_LONGNAME + jsdoc.name.INNER; result = jsdoc.name.LONGNAMES.ANONYMOUS + jsdoc.name.SCOPE.PUNC.INNER;
} }
else { else {
result = (doclet.longname || doclet.name) + jsdoc.name.INNER; result = (doclet.longname || doclet.name) + jsdoc.name.SCOPE.PUNC.INNER;
} }
} }
else { else {
@ -385,7 +385,7 @@ Parser.prototype.resolveThis = function(node) {
doclet = this._getDoclet(node.enclosingScope.nodeId); doclet = this._getDoclet(node.enclosingScope.nodeId);
if (!doclet) { if (!doclet) {
result = jsdoc.name.ANONYMOUS_LONGNAME; // TODO handle global this? result = jsdoc.name.LONGNAMES.ANONYMOUS; // TODO handle global this?
} }
else if (doclet['this']) { else if (doclet['this']) {
result = doclet['this']; result = doclet['this'];

View File

@ -24,8 +24,7 @@ var jsdoc = {
var path = require('jsdoc/path'); var path = require('jsdoc/path');
var Syntax = require('jsdoc/src/syntax').Syntax; var Syntax = require('jsdoc/src/syntax').Syntax;
var GLOBAL_LONGNAME = jsdoc.name.GLOBAL_LONGNAME; var NAMESPACES = jsdoc.name.NAMESPACES;
var MODULE_PREFIX = jsdoc.name.MODULE_PREFIX;
function getSourcePaths() { function getSourcePaths() {
var sourcePaths = env.sourceFiles.slice(0) || []; var sourcePaths = env.sourceFiles.slice(0) || [];
@ -474,7 +473,7 @@ exports.defineTags = function(dictionary) {
dictionary.defineTag('lends', { dictionary.defineTag('lends', {
onTagged: function(doclet, tag) { onTagged: function(doclet, tag) {
doclet.alias = tag.value || GLOBAL_LONGNAME; doclet.alias = tag.value || jsdoc.name.LONGNAMES.GLOBAL;
doclet.addTag('undocumented'); doclet.addTag('undocumented');
} }
}); });
@ -512,7 +511,7 @@ exports.defineTags = function(dictionary) {
onTagged: function(doclet, tag) { onTagged: function(doclet, tag) {
if (tag.originalTitle === 'memberof!') { if (tag.originalTitle === 'memberof!') {
doclet.forceMemberof = true; doclet.forceMemberof = true;
if (tag.value === GLOBAL_LONGNAME) { if (tag.value === jsdoc.name.LONGNAMES.GLOBAL) {
doclet.addTag('global'); doclet.addTag('global');
delete doclet.memberof; delete doclet.memberof;
} }
@ -628,8 +627,8 @@ exports.defineTags = function(dictionary) {
// otherwise, assume it's a module // otherwise, assume it's a module
else { else {
requiresName = firstWordOf(tag.value); requiresName = firstWordOf(tag.value);
if (requiresName.indexOf(MODULE_PREFIX) !== 0) { if (requiresName.indexOf(NAMESPACES.MODULE) !== 0) {
requiresName = MODULE_PREFIX + requiresName; requiresName = NAMESPACES.MODULE + requiresName;
} }
} }

View File

@ -9,6 +9,7 @@ var dictionary = require('jsdoc/tag/dictionary');
var util = require('util'); var util = require('util');
var hasOwnProp = Object.prototype.hasOwnProperty; var hasOwnProp = Object.prototype.hasOwnProperty;
var NAMESPACES = require('jsdoc/name').NAMESPACES;
var files = {}; var files = {};
@ -446,10 +447,8 @@ var find = exports.find = function(data, spec) {
* `false`. * `false`.
*/ */
function isModuleExports(doclet) { function isModuleExports(doclet) {
var MODULE_PREFIX = require('jsdoc/name').MODULE_PREFIX;
return doclet.longname && doclet.longname === doclet.name && return doclet.longname && doclet.longname === doclet.name &&
doclet.longname.indexOf(MODULE_PREFIX) === 0 && doclet.kind !== 'module'; doclet.longname.indexOf(NAMESPACES.MODULE) === 0 && doclet.kind !== 'module';
} }
/** /**

View File

@ -3,6 +3,7 @@
describe('jsdoc/doclet', function() { describe('jsdoc/doclet', function() {
// TODO: more tests // TODO: more tests
var _ = require('underscore');
var Doclet = require('jsdoc/doclet').Doclet; var Doclet = require('jsdoc/doclet').Doclet;
var debug = !!env.opts.debug; var debug = !!env.opts.debug;
@ -46,7 +47,7 @@ describe('jsdoc/doclet', function() {
doclet.setScope(scopeName); doclet.setScope(scopeName);
} }
Object.keys(require('jsdoc/name').SCOPE_NAMES).forEach(function(scopeName) { _.values(require('jsdoc/name').SCOPE.NAMES).forEach(function(scopeName) {
expect( setScope.bind(null, scopeName) ).not.toThrow(); expect( setScope.bind(null, scopeName) ).not.toThrow();
}); });
}); });

View File

@ -23,9 +23,9 @@ describe('jsdoc/name', function() {
}); });
// TODO: add tests for other exported constants // TODO: add tests for other exported constants
it('should export a SCOPE_NAMES enum', function() { it('should export a SCOPE enum', function() {
expect(jsdoc.name.SCOPE_NAMES).toBeDefined(); expect(jsdoc.name.SCOPE).toBeDefined();
expect(typeof jsdoc.name.SCOPE_NAMES).toBe('object'); expect(typeof jsdoc.name.SCOPE).toBe('object');
}); });
it("should export a 'shorten' function", function() { it("should export a 'shorten' function", function() {
@ -38,27 +38,56 @@ describe('jsdoc/name', function() {
expect(typeof jsdoc.name.splitName).toBe('function'); expect(typeof jsdoc.name.splitName).toBe('function');
}); });
describe('SCOPE_NAMES', function() { describe('SCOPE', function() {
var SCOPE_NAMES = jsdoc.name.SCOPE_NAMES; var SCOPE = jsdoc.name.SCOPE;
it('should have a "global" property', function() { it('should have a "NAMES" property', function() {
expect(SCOPE_NAMES.global).toBeDefined(); expect(SCOPE.NAMES).toBeDefined();
expect(typeof SCOPE_NAMES.global).toBe('string'); expect(typeof SCOPE.NAMES).toBe('object');
}); });
it('should have an "inner" property', function() { it('should have a "PUNC" property', function() {
expect(SCOPE_NAMES.inner).toBeDefined(); expect(SCOPE.PUNC).toBeDefined();
expect(typeof SCOPE_NAMES.inner).toBe('string'); expect(typeof SCOPE.PUNC).toBe('object');
}); });
it('should have an "instance" property', function() { describe('NAMES', function() {
expect(SCOPE_NAMES.instance).toBeDefined(); it('should have a "GLOBAL" property', function() {
expect(typeof SCOPE_NAMES.instance).toBe('string'); expect(SCOPE.NAMES.GLOBAL).toBeDefined();
expect(typeof SCOPE.NAMES.GLOBAL).toBe('string');
});
it('should have an "INNER" property', function() {
expect(SCOPE.NAMES.INNER).toBeDefined();
expect(typeof SCOPE.NAMES.INNER).toBe('string');
});
it('should have an "INSTANCE" property', function() {
expect(SCOPE.NAMES.INSTANCE).toBeDefined();
expect(typeof SCOPE.NAMES.INSTANCE).toBe('string');
});
it('should have a "STATIC" property', function() {
expect(SCOPE.NAMES.STATIC).toBeDefined();
expect(typeof SCOPE.NAMES.STATIC).toBe('string');
});
}); });
it('should have a "static" property', function() { describe('PUNC', function() {
expect(SCOPE_NAMES.static).toBeDefined(); it('should have an "INNER" property', function() {
expect(typeof SCOPE_NAMES.static).toBe('string'); expect(SCOPE.PUNC.INNER).toBeDefined();
expect(typeof SCOPE.PUNC.INNER).toBe('string');
});
it('should have an "INSTANCE" property', function() {
expect(SCOPE.PUNC.INSTANCE).toBeDefined();
expect(typeof SCOPE.PUNC.INSTANCE).toBe('string');
});
it('should have a "STATIC" property', function() {
expect(SCOPE.PUNC.STATIC).toBeDefined();
expect(typeof SCOPE.PUNC.STATIC).toBe('string');
});
}); });
}); });