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) {
var globalRegexp = new RegExp('^' + jsdoc.name.GLOBAL_LONGNAME + '\\.?');
var globalRegexp = new RegExp('^' + jsdoc.name.LONGNAMES.GLOBAL + '\\.?');
return longname.replace(globalRegexp, '');
}
@ -233,7 +233,7 @@ Doclet.prototype.setMemberof = function(sid) {
* @type string
*/
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
* {@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.
* @throws {Error} If the scope name is not recognized.
*/
Doclet.prototype.setScope = function(scope) {
var errorMessage;
var filepath;
var scopeNames = Object.keys(jsdoc.name.SCOPE_NAMES);
var scopeNames = _.values(jsdoc.name.SCOPE.NAMES);
if (scopeNames.indexOf(scope) === -1) {
filepath = getFilepath(this);
errorMessage = util.format('The scope name "%s" is not recognized. Use one of the names ' +
'defined in module:jsdoc/name.SCOPE_NAMES.', scope);
errorMessage = util.format('The scope name "%s" is not recognized. Use one of the ' +
'following values: %j', scope, scopeNames);
if (filepath) {
errorMessage += util.format(' (Source file: %s)', filepath);
}

View File

@ -8,30 +8,64 @@
var _ = require('underscore');
// Longname used for doclets whose actual longname cannot be identified.
var ANONYMOUS_LONGNAME = exports.ANONYMOUS_LONGNAME = '<anonymous>';
// Longname used for doclets in global scope.
var GLOBAL_LONGNAME = exports.GLOBAL_LONGNAME = '<global>';
var INNER = exports.INNER = '~';
var INSTANCE = exports.INSTANCE = '#';
var MODULE_PREFIX = exports.MODULE_PREFIX = 'module:';
// Scope identifiers.
var SCOPE_NAMES = exports.SCOPE_NAMES = {
global: 'global',
inner: 'inner',
instance: 'instance',
'static': 'static'
/**
* Longnames that have a special meaning in JSDoc.
*
* @enum {string}
* @static
* @memberof module:jsdoc/name
*/
var LONGNAMES = exports.LONGNAMES = {
/** Longname used for doclets that do not have a longname, such as anonymous functions. */
ANONYMOUS: '<anonymous>',
/** Longname that represents global scope. */
GLOBAL: '<global>'
};
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 = {
'inner': INNER,
'instance': INSTANCE,
'static': STATIC
'inner': SCOPE.PUNC.INNER,
'instance': SCOPE.PUNC.INSTANCE,
'static': SCOPE.PUNC.STATIC
};
var puncToScope = exports.puncToScope = _.invert(scopeToPunc);
var DEFAULT_SCOPE = SCOPE_NAMES.static;
var REGEXP_SCOPE_PUNC = '([' + INNER + INSTANCE + STATIC + '])';
var DEFAULT_SCOPE = SCOPE.NAMES.STATIC;
var REGEXP_SCOPE_PUNC = '([' + _.values(SCOPE.PUNC) + '])';
var REGEXP_LEADING_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) {
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?
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
@ -78,7 +112,7 @@ exports.resolve = function(doclet) {
}
// the name and memberof are identical and refer to a module,
// 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));
}
// the name and memberof are identical, like @name foo, @memberof foo
@ -117,7 +151,7 @@ exports.resolve = function(doclet) {
delete doclet.memberof;
}
else if (about.scope) {
if (about.memberof === GLOBAL_LONGNAME) { // via @memberof <global> ?
if (about.memberof === LONGNAMES.GLOBAL) { // via @memberof <global> ?
doclet.scope = 'global';
}
else {

View File

@ -10,7 +10,7 @@ var uid = 100000000;
// TODO: docs
// 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.

View File

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

View File

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

View File

@ -9,6 +9,7 @@ var dictionary = require('jsdoc/tag/dictionary');
var util = require('util');
var hasOwnProp = Object.prototype.hasOwnProperty;
var NAMESPACES = require('jsdoc/name').NAMESPACES;
var files = {};
@ -446,10 +447,8 @@ var find = exports.find = function(data, spec) {
* `false`.
*/
function isModuleExports(doclet) {
var MODULE_PREFIX = require('jsdoc/name').MODULE_PREFIX;
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() {
// TODO: more tests
var _ = require('underscore');
var Doclet = require('jsdoc/doclet').Doclet;
var debug = !!env.opts.debug;
@ -46,7 +47,7 @@ describe('jsdoc/doclet', function() {
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();
});
});

View File

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