mirror of
https://github.com/jsdoc/jsdoc.git
synced 2026-02-01 16:45:41 +00:00
Added tests for @file, @returns, and @type.
This commit is contained in:
parent
666dd53143
commit
22cb3d2ef6
@ -33,7 +33,7 @@
|
||||
tags = parse_tag.parse(commentSrc);
|
||||
|
||||
try {
|
||||
preprocess(tags);
|
||||
preprocess(tags, meta);
|
||||
}
|
||||
catch(e) {
|
||||
e.message = 'Cannot make doclet from JSDoc comment found at '+ meta.file + ' ' + meta.line
|
||||
@ -45,7 +45,7 @@
|
||||
doclet = new Doclet(tags);
|
||||
|
||||
doclet.meta = meta;
|
||||
|
||||
|
||||
postprocess(doclet);
|
||||
|
||||
name.resolve(doclet);
|
||||
@ -73,33 +73,44 @@
|
||||
@param {string name
|
||||
*/
|
||||
Doclet.prototype.setName = function(nameToSet) {
|
||||
this.tagText('name', nameToSet);
|
||||
this.setTag('name', nameToSet);
|
||||
|
||||
nameToSet = name.resolve(this);
|
||||
}
|
||||
|
||||
/**
|
||||
Return the text of the last tag with the given name.
|
||||
@method Doclet#tagText
|
||||
Return the value of the last tag with the given name.
|
||||
@method Doclet#tagValue
|
||||
@param {String} tagName
|
||||
@returns {String} The text of the found tag.
|
||||
@returns {*} The value of the found tag.
|
||||
*/
|
||||
Doclet.prototype.tagText = function(tagName, text) {
|
||||
var i = this.tags.length;
|
||||
while(i--) {
|
||||
Doclet.prototype.tagValue = function(tagName) {
|
||||
for (var i = 0, leni = this.tags.length; i < leni; i++) {
|
||||
if (this.tags[i].name === tagName) {
|
||||
if (text) { this.tags[i].text = text; }
|
||||
return this.tags[i].text;
|
||||
return this.tags[i].value;
|
||||
}
|
||||
}
|
||||
|
||||
// still here?
|
||||
if (text) {
|
||||
this.tags.push( parse_tag.fromTagText(tagName + ' ' + text) );
|
||||
return text;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Return the value of the last tag with the given name.
|
||||
@method Doclet#setTag
|
||||
@param {String} tagName
|
||||
@returns {*} The value of the found tag.
|
||||
*/
|
||||
Doclet.prototype.setTag = function(tagName, tagValue) {
|
||||
|
||||
for (var i = 0, leni = this.tags.length; i < leni; i++) {
|
||||
if (this.tags[i].name === tagName) {
|
||||
this.tags[i].value = tagValue;
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
|
||||
this.tags[this.tags.length] = parse_tag.fromText(tagName + ' ' + tagValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -154,10 +165,10 @@
|
||||
// tag value is not an object, it's just a simple string
|
||||
if (!tag.pname && !tag.pdesc && !(tag.type && tag.type.length)) { // TODO: should check the list instead?
|
||||
if (flavor === 'xml' && tagName === 'example') {
|
||||
tagValue['#cdata'] = tag.text; // TODO this is only meaningful to XML, move to a tag.format(style) method?
|
||||
tagValue['#cdata'] = tag.value; // TODO this is only meaningful to XML, move to a tag.format(style) method?
|
||||
}
|
||||
else {
|
||||
tagValue = tag.text;
|
||||
tagValue = tag.value;
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,6 +187,7 @@
|
||||
|
||||
o.meta = this.meta;
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
@ -228,48 +240,49 @@
|
||||
@param {Array.<Object>} tags
|
||||
@returns undefined
|
||||
*/
|
||||
function preprocess(tags) {
|
||||
function preprocess(tags, meta) {
|
||||
var name = '',
|
||||
taggedName = '',
|
||||
isa = '',
|
||||
taggedDenom = '',
|
||||
taggedIsa = '',
|
||||
memberof = '',
|
||||
taggedMemberof = '';
|
||||
taggedMemberof = '',
|
||||
isFile = false;
|
||||
|
||||
for (var i = 0, leni = tags.length; i < leni; i++) {
|
||||
|
||||
if (tags[i].name === 'private') {
|
||||
tags[tags.length] = parse_tag.fromTagText('access private');
|
||||
tags[tags.length] = parse_tag.fromText('access private');
|
||||
}
|
||||
else if (tags[i].name === 'protected') {
|
||||
tags[tags.length] = parse_tag.fromTagText('access protected');
|
||||
tags[tags.length] = parse_tag.fromText('access protected');
|
||||
}
|
||||
else if (tags[i].name === 'public') {
|
||||
tags[tags.length] = parse_tag.fromTagText('access public');
|
||||
tags[tags.length] = parse_tag.fromText('access public');
|
||||
}
|
||||
else if (tags[i].name === 'const') {
|
||||
tags[tags.length] = parse_tag.fromTagText('attribute constant');
|
||||
tags[tags.length] = parse_tag.fromText('attribute constant');
|
||||
}
|
||||
else if (tags[i].name === 'readonly') {
|
||||
tags[tags.length] = parse_tag.fromTagText('attribute readonly');
|
||||
tags[tags.length] = parse_tag.fromText('attribute readonly');
|
||||
}
|
||||
else if (tags[i].name === 'name') {
|
||||
if (name && name !== tags[i].text) {
|
||||
throw new DocTagConflictError('Conflicting names in documentation: '+name+', '+tags[i].text);
|
||||
if (name && name !== tags[i].value) {
|
||||
throw new DocTagConflictError('Conflicting names in documentation: '+name+', '+tags[i].value);
|
||||
}
|
||||
taggedName = name = tags[i].text;
|
||||
taggedName = name = tags[i].value;
|
||||
}
|
||||
else if (tags[i].name === 'isa') {
|
||||
if (isa && isa !== tags[i].text) {
|
||||
throw new DocTagConflictError('Symbol has too many denominations, cannot be both: ' + isa + ' and ' + tags[i].text);
|
||||
if (isa && isa !== tags[i].value) {
|
||||
throw new DocTagConflictError('Symbol has too many denominations, cannot be both: ' + isa + ' and ' + tags[i].value);
|
||||
}
|
||||
taggedDenom = isa = tags[i].text;
|
||||
taggedIsa = isa = tags[i].value;
|
||||
}
|
||||
else if (tags[i].name === 'memberof') {
|
||||
if (memberof) {
|
||||
throw new DocTagConflictError('doclet has too many tags of type: @memberof.');
|
||||
}
|
||||
taggedMemberof = memberof = tags[i].text;
|
||||
taggedMemberof = memberof = tags[i].value;
|
||||
}
|
||||
|
||||
if ( nameables.indexOf(tags[i].name) > -1 ) {
|
||||
@ -277,19 +290,15 @@
|
||||
// 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);
|
||||
if (tags[i].value) {
|
||||
if (name && name !== tags[i].value) {
|
||||
throw new DocTagConflictError('Conflicting names in documentation: '+name+', '+tags[i].value);
|
||||
}
|
||||
name = tags[i].text;
|
||||
name = tags[i].value;
|
||||
}
|
||||
|
||||
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('|'));
|
||||
tags[tags.length] = parse_tag.fromText('desc ' + tags[i].pdesc);
|
||||
}
|
||||
|
||||
if (isa && isa !== tags[i].name) {
|
||||
@ -299,13 +308,17 @@
|
||||
if (isa === 'const') { isa = 'property'; } // an exception to the namebale rule
|
||||
}
|
||||
}
|
||||
else if (tags[i].name === 'file') { // the only isa which cannot have a name after @file
|
||||
isFile = true;
|
||||
isa = 'file';
|
||||
}
|
||||
|
||||
if ( memberofs.hasOwnProperty(tags[i].name) ) {
|
||||
if (tags[i].text) {
|
||||
if (tags[i].value) {
|
||||
if (memberof) {
|
||||
throw new DocTagConflictError('doclet has too many tags of type: @memberof.');
|
||||
}
|
||||
memberof = tags[i].text;
|
||||
memberof = tags[i].value;
|
||||
}
|
||||
|
||||
if (isa && isa !== memberofs[tags[i].name]) {
|
||||
@ -316,47 +329,51 @@
|
||||
}
|
||||
|
||||
if (name && !taggedName) {
|
||||
tags[tags.length] = parse_tag.fromTagText('name ' + name);
|
||||
tags[tags.length] = parse_tag.fromText('name ' + name);
|
||||
}
|
||||
|
||||
if (isa && !taggedDenom) {
|
||||
tags[tags.length] = parse_tag.fromTagText('isa ' + isa);
|
||||
if ( isFile && !(name || taggedName) ) {
|
||||
tags[tags.length] = parse_tag.fromText('name file:'+meta.file+'');
|
||||
}
|
||||
|
||||
if (isa && !taggedIsa) {
|
||||
tags[tags.length] = parse_tag.fromText('isa ' + isa);
|
||||
}
|
||||
|
||||
if (memberof && !taggedMemberof) {
|
||||
tags[tags.length] = parse_tag.fromTagText('memberof ' + memberof);
|
||||
tags[tags.length] = parse_tag.fromText('memberof ' + memberof);
|
||||
}
|
||||
}
|
||||
|
||||
function postprocess(doclet) {
|
||||
if ( doclet.hasTag('class') && !doclet.hasTag('constructor') ) {
|
||||
doclet.tags[doclet.tags.length] = parse_tag.fromTagText('isa constructor');
|
||||
doclet.tags[doclet.tags.length] = parse_tag.fromText('isa constructor');
|
||||
}
|
||||
|
||||
if ( doclet.hasTag('enum')) {
|
||||
if (!doclet.hasTag('type')) {
|
||||
doclet.tags[doclet.tags.length] = parse_tag.fromTagText('type number');
|
||||
if ( doclet.hasTag('enum') ) {
|
||||
if ( !doclet.hasTag('type') ) {
|
||||
doclet.tags[doclet.tags.length] = parse_tag.fromText('type number');
|
||||
}
|
||||
|
||||
if (!doclet.hasTag('readonly') && !doclet.hasTag('const')) {
|
||||
doclet.tags[doclet.tags.length] = parse_tag.fromTagText('attribute constant');
|
||||
if ( !doclet.hasTag('readonly') && !doclet.hasTag('const') ) {
|
||||
doclet.tags[doclet.tags.length] = parse_tag.fromText('attribute constant');
|
||||
}
|
||||
}
|
||||
|
||||
if ( doclet.hasTag('const')) {
|
||||
if (!doclet.hasTag('isa')) {
|
||||
doclet.tags[doclet.tags.length] = parse_tag.fromTagText('isa property');
|
||||
if ( doclet.hasTag('const') ) {
|
||||
if ( !doclet.hasTag('isa') ) {
|
||||
doclet.tags[doclet.tags.length] = parse_tag.fromText('isa property');
|
||||
}
|
||||
|
||||
if (!doclet.hasTag('readonly') && !doclet.hasTag('const')) {
|
||||
doclet.tags[doclet.tags.length] = parse_tag.fromTagText('attribute constant');
|
||||
doclet.tags[doclet.tags.length] = parse_tag.fromText('attribute constant');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function DocTagConflictError(message) {
|
||||
this.name = "DocTagConflictError";
|
||||
this.message = (message || "");
|
||||
this.name = 'DocTagConflictError';
|
||||
this.message = (message || '');
|
||||
}
|
||||
DocTagConflictError.prototype = Error.prototype;
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
i = doclets.length;
|
||||
|
||||
while (i--) {
|
||||
if (doclets[i].tagText('path') === docName) {
|
||||
if (doclets[i].tagValue('path') === docName) {
|
||||
foundDocs.unshift( doclets[i] );
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,15 +23,15 @@
|
||||
@param {Doclet} doclet
|
||||
*/
|
||||
exports.resolve = function(doclet) {
|
||||
var isa = doclet.tagText('isa'),
|
||||
var isa = doclet.tagValue('isa'),
|
||||
ns = '',
|
||||
name = doclet.tagText('name'),
|
||||
memberof = doclet.tagText('memberof'),
|
||||
name = doclet.tagValue('name') || '',
|
||||
memberof = doclet.tagValue('memberof') || '',
|
||||
path,
|
||||
shortname,
|
||||
prefix,
|
||||
supportedNamespaces = ['module', 'event'];
|
||||
|
||||
supportedNamespaces = ['module', 'event', 'file'];
|
||||
|
||||
// only keep the first word of the first tagged name
|
||||
name = name.split(/\s+/g)[0];
|
||||
|
||||
@ -42,9 +42,7 @@
|
||||
name = name.replace(/\.prototype\.?/g, '#');
|
||||
|
||||
path = shortname = name;
|
||||
|
||||
|
||||
|
||||
|
||||
if (memberof) {
|
||||
// like @name foo.bar, @memberof foo
|
||||
if (name.indexOf(memberof) === 0) {
|
||||
@ -52,9 +50,9 @@
|
||||
[prefix, name] = exports.shorten(name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
else if (isa !== 'file') {
|
||||
[memberof, name] = exports.shorten(name);
|
||||
doclet.tagText('memberof', memberof);
|
||||
if (memberof) { doclet.setTag('memberof', memberof); }
|
||||
}
|
||||
|
||||
// if name doesn't already have a doc-namespace and needs one
|
||||
@ -67,28 +65,43 @@
|
||||
// add doc-namespace to path
|
||||
ns = isa + ':';
|
||||
}
|
||||
|
||||
doclet.tagText('name', name);
|
||||
|
||||
if (name) doclet.setTag('name', name);
|
||||
|
||||
if (memberof && name.indexOf(memberof) !== 0) {
|
||||
path = memberof + (/#$/.test(memberof)? '' : '.') + ns + name;
|
||||
}
|
||||
|
||||
|
||||
if (path) {
|
||||
doclet.tagText('path', path);
|
||||
doclet.setTag('path', path);
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
exports.shorten = function(path) {
|
||||
// quoted strings in a path are atomic
|
||||
var atoms = [],
|
||||
cursor = 0;
|
||||
path = path.replace(/(".+?")/g, function($) {
|
||||
var token = '@' + atoms.length + '@';
|
||||
atoms.push($);
|
||||
return token;
|
||||
});
|
||||
|
||||
var shortname = path.split(/([#.-])/).pop(),
|
||||
splitOn = RegExp.$1,
|
||||
splitAt = path.lastIndexOf(splitOn),
|
||||
prefix = (splitOn && splitAt !== -1)? path.slice(0, splitAt) : '';
|
||||
|
||||
if (splitOn === '#') { prefix = prefix + splitOn; }
|
||||
|
||||
// restore quoted strings back again
|
||||
for (var i = 0, leni = atoms.length; i < leni; i++) {
|
||||
prefix = prefix.replace('@'+i+'@', atoms[i]);
|
||||
shortname = shortname.replace('@'+i+'@', atoms[i]);
|
||||
}
|
||||
|
||||
return [prefix, shortname];
|
||||
}
|
||||
|
||||
@ -98,12 +111,12 @@
|
||||
exports.resolveThis = function(name, node, doclet) {
|
||||
var enclosing,
|
||||
enclosingDoc,
|
||||
memberof = (doclet.tagText('memberof') || '').replace(/\.prototype\.?/g, '#');
|
||||
memberof = (doclet.tagValue('memberof') || '').replace(/\.prototype\.?/g, '#');
|
||||
|
||||
if (node.parent && node.parent.type === Token.OBJECTLIT) {
|
||||
if (enclosing = node.parent) {
|
||||
enclosingDoc = exports.docFromNode(enclosing) || {};
|
||||
memberof = (enclosingDoc.tagText('path') || '').replace(/\.prototype\.?/g, '#');
|
||||
memberof = (enclosingDoc.tagValue('path') || '').replace(/\.prototype\.?/g, '#');
|
||||
|
||||
if (!memberof) {
|
||||
memberof = enclosingDoc.path;
|
||||
@ -120,7 +133,7 @@
|
||||
enclosing = node.getEnclosingFunction()
|
||||
|
||||
enclosingDoc = exports.docFromNode(enclosing);
|
||||
memberof = enclosingDoc? enclosingDoc.tagText('path') : '';
|
||||
memberof = enclosingDoc? enclosingDoc.tagValue('path') : '';
|
||||
|
||||
if (enclosing && !memberof) {
|
||||
memberof = ''; //[[anonymousFunction]]
|
||||
@ -132,7 +145,7 @@
|
||||
|
||||
if (memberof || !enclosing) {
|
||||
// `this` refers to nearest instance in the name path
|
||||
if (enclosingDoc && enclosingDoc.tagText('isa') !== 'constructor') {
|
||||
if (enclosingDoc && enclosingDoc.tagValue('isa') !== 'constructor') {
|
||||
var parts = memberof.split('#');
|
||||
parts.pop();
|
||||
memberof = parts.join('#');
|
||||
|
||||
@ -12,37 +12,40 @@
|
||||
var commentSrc = '',
|
||||
thisDoclet = null,
|
||||
thisDocletName = '';
|
||||
|
||||
// look for all comments that have names provided
|
||||
if (node.type === Token.SCRIPT && node.comments) {
|
||||
for each (var comment in node.comments.toArray()) {
|
||||
if (comment.commentType === Token.CommentType.JSDOC) {
|
||||
commentSrc = '' + comment.toSource();
|
||||
|
||||
if (commentSrc) {
|
||||
thisDoclet = doclet.makeDoclet(commentSrc, comment, currentSourceName);
|
||||
if ( thisDoclet.hasTag('name') ) {
|
||||
doclets.push(thisDoclet);
|
||||
if (thisDoclet.tagText('isa') === 'module') {
|
||||
name.setCurrentModule( thisDoclet.tagText('path') );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// look for all comments that have names provided
|
||||
if (node.type === Token.SCRIPT && node.comments) {
|
||||
for each (var comment in node.comments.toArray()) {
|
||||
if (comment.commentType === Token.CommentType.JSDOC) {
|
||||
commentSrc = '' + comment.toSource();
|
||||
if (commentSrc) {
|
||||
thisDoclet = doclet.makeDoclet(commentSrc, comment, currentSourceName);
|
||||
|
||||
if ( thisDoclet.hasTag('name') ) {
|
||||
doclets.push(thisDoclet);
|
||||
if (thisDoclet.tagValue('isa') === 'module') {
|
||||
name.setCurrentModule( thisDoclet.tagValue('path') );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// like function foo() {}
|
||||
if (node.type == Token.FUNCTION) {
|
||||
|
||||
if (node.jsDoc) {
|
||||
commentSrc = '' + node.jsDoc;
|
||||
|
||||
|
||||
if (commentSrc) {
|
||||
thisDoclet = doclet.makeDoclet(commentSrc, node, currentSourceName);
|
||||
thisDocletName = thisDoclet.tagText('path');
|
||||
|
||||
thisDocletName = thisDoclet.tagValue('path');
|
||||
|
||||
if (!thisDocletName) {
|
||||
thisDoclet.setName('' + node.name);
|
||||
|
||||
doclets.push(thisDoclet);
|
||||
}
|
||||
|
||||
@ -63,8 +66,8 @@
|
||||
commentSrc = '' + commentSrc;
|
||||
|
||||
thisDoclet = doclet.makeDoclet(commentSrc, node, currentSourceName);
|
||||
thisDocletName = thisDoclet.tagText('name');
|
||||
nodeKind = thisDoclet.tagText('isa');
|
||||
thisDocletName = thisDoclet.tagValue('name');
|
||||
nodeKind = thisDoclet.tagValue('isa');
|
||||
|
||||
if (!thisDocletName) {
|
||||
nodeName = name.resolveThis( nodeName, node, thisDoclet );
|
||||
@ -88,8 +91,8 @@
|
||||
commentSrc = (counter++ === 0 && !n.jsDoc)? node.jsDoc : n.jsDoc;
|
||||
if (commentSrc) {
|
||||
thisDoclet = doclet.makeDoclet('' + commentSrc, node, currentSourceName);
|
||||
thisDocletName = thisDoclet.tagText('path');
|
||||
nodeKind = thisDoclet.tagText('isa');
|
||||
thisDocletName = thisDoclet.tagValue('path');
|
||||
nodeKind = thisDoclet.tagValue('isa');
|
||||
|
||||
if ( !thisDocletName ) {
|
||||
thisDocletName = n.target.string;
|
||||
|
||||
@ -5,16 +5,22 @@
|
||||
@see <http://tools.ietf.org/html/draft-zyp-json-schema-02>
|
||||
*/
|
||||
|
||||
var jsdoc = jsdoc || {};
|
||||
jsdoc.schema = (typeof exports === 'undefined')? {} : exports; // like commonjs
|
||||
|
||||
jsdoc.schema.jsdocSchema = {
|
||||
exports.jsdocSchema = {
|
||||
"properties": {
|
||||
"doc": {
|
||||
"docnode": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"maxItems": 1
|
||||
},
|
||||
"summary": {
|
||||
"type": "string",
|
||||
"maxItems": 1
|
||||
},
|
||||
"desc": {
|
||||
"type": "string",
|
||||
"maxItems": 1
|
||||
},
|
||||
@ -30,30 +36,130 @@ jsdoc.schema.jsdocSchema = {
|
||||
"isa": {
|
||||
"type": "string",
|
||||
"maxItems": 1,
|
||||
"enum": ["constructor", "module", "event", "namespace", "method", "member", "enum"]
|
||||
"enum": ["constructor", "module", "event", "namespace", "method", "property", "enum", "class", "interface", "constant", "file"]
|
||||
},
|
||||
"access": {
|
||||
"type": "string",
|
||||
"maxItems": 1,
|
||||
"enum": ["private", "protected", "public"]
|
||||
},
|
||||
"type": {
|
||||
"type": "array",
|
||||
"optional": true,
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"param" : {
|
||||
"type": "array",
|
||||
"optional": true,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "array",
|
||||
"optional": true,
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"isoptional": {
|
||||
"type": "boolean",
|
||||
"optional": true,
|
||||
"default": true
|
||||
},
|
||||
"isnullable": {
|
||||
"type": "boolean",
|
||||
"optional": true,
|
||||
"default": true
|
||||
},
|
||||
"defaultvalue": {
|
||||
"optional": true
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
},
|
||||
"desc": {
|
||||
"type": "string",
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
"meta": {
|
||||
"type": "object",
|
||||
"optional": true,
|
||||
"maxItems": 1,
|
||||
"file": {
|
||||
"type": "string",
|
||||
"optional": true,
|
||||
"maxItems": 1
|
||||
},
|
||||
"line": {
|
||||
"type": "number",
|
||||
"optional": true,
|
||||
"maxItems": 1
|
||||
},
|
||||
"category": {
|
||||
"type": "string",
|
||||
"optional": true,
|
||||
"maxItems": 1
|
||||
},
|
||||
"optional": true,
|
||||
"maxItems": 1
|
||||
"tags": {
|
||||
"type": "array",
|
||||
"optional": true,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"tagname": {
|
||||
"type": "string"
|
||||
},
|
||||
"tagtext": {
|
||||
"type": "string",
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"type": "object",
|
||||
"optional": true,
|
||||
"date": {
|
||||
"type": "string",
|
||||
"maxItems": 1
|
||||
"maxItems": 1,
|
||||
"project": {
|
||||
"type": "object",
|
||||
"optional": true,
|
||||
"maxItems": 1,
|
||||
"name": {
|
||||
"type": "string",
|
||||
"maxItems": 1
|
||||
},
|
||||
"uri": {
|
||||
"type": "string",
|
||||
"maxItems": 1,
|
||||
"format": "uri"
|
||||
}
|
||||
},
|
||||
"generated": {
|
||||
"type": "object",
|
||||
"optional": true,
|
||||
"maxItems": 1,
|
||||
"date": {
|
||||
"type": "string",
|
||||
"maxItems": 1,
|
||||
"optional": true,
|
||||
"format": "date-time"
|
||||
},
|
||||
"parser": {
|
||||
"type": "string",
|
||||
"maxItems": 1,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,73 +9,95 @@
|
||||
@module jsdoc/tag
|
||||
*/
|
||||
(function() {
|
||||
var jsdoc_type = require('jsdoc/type');
|
||||
var jsdoc_type = require('jsdoc/type'),
|
||||
tagz = require('jsdoc/tagdictionary').TagDictionary;
|
||||
|
||||
exports.fromTagText = function(tagText) {
|
||||
return new Tag(tagText);
|
||||
exports.fromText = function(tagText) {
|
||||
var tag = new Tag(tagText);
|
||||
return tag;
|
||||
}
|
||||
|
||||
// tags that have {type} (name desc|text)
|
||||
var longTags = ['param', 'constructor', 'const', 'module', 'event', 'namespace', 'method', 'member', 'function', 'variable', 'enum', 'returns'];
|
||||
var longTags = ['param', 'constructor', 'type', 'const', 'module', 'event', 'namespace', 'method', 'member', 'function', 'variable', 'enum', 'returns'];
|
||||
// tags that have {type} text
|
||||
var anonTags = ['returns'];
|
||||
|
||||
/**
|
||||
@private
|
||||
@constructor Tag
|
||||
@constructor module:jsdoc/tag.Tag
|
||||
@param {string} tagText
|
||||
*/
|
||||
function Tag(tagText) {
|
||||
/** @property {string} - The raw text of this tag, include everything after the @. */
|
||||
this.raw = tagText;
|
||||
|
||||
/** @property {string} - The name of this tag, the word adjacent to the @. */
|
||||
this.name = '';
|
||||
|
||||
/** @property {Array} - Zero or more type specifiers. */
|
||||
this.type = [];
|
||||
this.text = '';
|
||||
|
||||
/** @property {*} - The value of this tag. */
|
||||
this.value = null;
|
||||
|
||||
/** @property {string} - If this is a long tag, then this will be the parameter name. */
|
||||
this.pname = '';
|
||||
|
||||
/** @property {string} - If this is a long tag, then this will be the parameter description. */
|
||||
this.pdesc = '';
|
||||
|
||||
// tagText is like: "tagname tag text"
|
||||
var bits = tagText.match(/^\s*(\S+)(?:\s([\s\S]*))?$/);
|
||||
|
||||
if (bits) {
|
||||
this.name = (bits[1] || '').toLowerCase(); // like @name
|
||||
this.name = trim( resolveSynonyms(this.name) );
|
||||
|
||||
this.text = bits[2] || ''; // all the rest of the tag
|
||||
// raw is like: "tagname andsometagtext"
|
||||
var parts = this.raw.match(/^\s*(\S+)(?:\s+([\s\S]*))?$/);
|
||||
|
||||
if (this.name !== 'example') { // example is the only tag that preserves whitespace
|
||||
this.text = trim( this.text );
|
||||
if (parts) {
|
||||
this.name = (parts[1] || '').toLowerCase(); // like @name
|
||||
this.name = resolveSynonyms(this.name);
|
||||
|
||||
tagText = parts[2] || ''; // all the rest of the tag
|
||||
|
||||
if (tagz.lookUp(this.name).keepsWhitespace) {
|
||||
this.value = tagText;
|
||||
}
|
||||
else {
|
||||
this.value = trim(tagText);
|
||||
}
|
||||
|
||||
if (longTags.indexOf(this.name) > -1) { // is a tag that uses the long format
|
||||
|
||||
var /*Array.<string>*/ type,
|
||||
/*string*/ text,
|
||||
/*any*/ value,
|
||||
/*?boolean*/ optional,
|
||||
/*?boolean*/ nullable;
|
||||
[type, text, optional, nullable] = jsdoc_type.parse(this.text);
|
||||
|
||||
// @type tags are the only tag that is not allowed to have a {type}!
|
||||
if (this.name === 'type') {
|
||||
text = text || type.join('|');
|
||||
type = [];
|
||||
}
|
||||
|
||||
[type, value, optional, nullable] = jsdoc_type.parse(this.value);
|
||||
|
||||
// don't add an empty type or null attributes
|
||||
if (type && type.length) { this.type = type; }
|
||||
|
||||
// @type tags are special: the only tag that is not allowed to have a {type}
|
||||
// their type becomes their value
|
||||
if (this.name === 'type') {
|
||||
value = (this.type[0] === '')? this.value.split(/\s*\|\s*/g) : this.type;
|
||||
if (value.length === 1) value = value[0]; // single values don't need to be arrays
|
||||
this.type = [];
|
||||
}
|
||||
|
||||
if (optional !== null) { this.poptional = optional; }
|
||||
if (nullable !== null) { this.pnullable = nullable; }
|
||||
|
||||
this.text = text;
|
||||
|
||||
if (anonTags.indexOf(this.name) > -1) {
|
||||
this.pdesc = this.text;
|
||||
// TODO protect @example from being overwritten?
|
||||
this.value = value;
|
||||
if (tagz.lookUp(this.name).canHavePname && tagz.lookUp(this.name).canHavePdesc) { // some tags just have {type} desc
|
||||
if (typeof this.value === 'string') {
|
||||
var [pname, pdesc, poptional, pdefault] = parsePname(this.value);
|
||||
this.pname = pname;
|
||||
this.pdesc = pdesc;
|
||||
if (typeof poptional !== 'undefined') this.poptional = poptional;
|
||||
this.pdefault = pdefault;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
var [pname, pdesc, poptional, pdefault] = parsePname(this.text);
|
||||
this.pname = pname;
|
||||
this.pdesc = pdesc;
|
||||
if (typeof poptional !== 'undefined') this.poptional = poptional;
|
||||
this.pdefault = pdefault;
|
||||
else if (tagz.lookUp(this.name).canHavePdesc) {
|
||||
this.pdesc = this.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -85,8 +107,8 @@
|
||||
Given the source of a jsdoc comment, finds the tags.
|
||||
@private
|
||||
@function parse
|
||||
@param {string} commentSrc Unwrapped.
|
||||
@returns Array.<Object>
|
||||
@param {string} commentSrc Unwrapped raw source of the doc comment.
|
||||
@returns {Array.<module:jsdoc/tag.Tag>}
|
||||
*/
|
||||
exports.parse = function(commentSrc) {
|
||||
var tags = [];
|
||||
@ -96,7 +118,7 @@
|
||||
.replace(/^(\s*)@(\S)/gm, '$1\\@$2') // replace splitter ats with an arbitrary sequence (unicode_recordseperator+@)
|
||||
.split('\\@') // then split on that arbitrary sequence
|
||||
.forEach(function($) {
|
||||
var newTag = exports.fromTagText($);
|
||||
var newTag = exports.fromText($);
|
||||
|
||||
if (newTag.name) { tags.push(newTag); }
|
||||
});
|
||||
@ -109,19 +131,20 @@
|
||||
}
|
||||
|
||||
/**
|
||||
Split the parameter name and parameter desc from the tag text.
|
||||
Parse the parameter name and parameter desc from the tag text.
|
||||
@private
|
||||
@method parsePname
|
||||
@param {string} tagText
|
||||
@returns Array.<string> The pname and the pdesc.
|
||||
@returns {Array.<string, string, boolean, boolean>} [pname, pdesc, poptional, pdefault].
|
||||
*/
|
||||
function parsePname(tagText) {
|
||||
var pname, pdesc, poptional, pdefault;
|
||||
|
||||
tagText.match(/^(\[[^\]]+\]|\S+)(\s+(\S[\s\S]*))?$/);
|
||||
// like: pname, pname pdesc, or name - pdesc
|
||||
tagText.match(/^(\[[^\]]+\]|\S+)((?:\s*\-\s*|\s+)(\S[\s\S]*))?$/);
|
||||
pname = RegExp.$1;
|
||||
pdesc = RegExp.$3;
|
||||
|
||||
|
||||
if ( /^\[\s*(.+?)\s*\]$/.test(pname) ) {
|
||||
pname = RegExp.$1;
|
||||
poptional = true;
|
||||
@ -143,11 +166,14 @@
|
||||
}
|
||||
}
|
||||
exports.synonyms = {
|
||||
/*synonym*/ /*canonical*/
|
||||
'description': 'desc',
|
||||
'function': 'method',
|
||||
'variable': 'property',
|
||||
'return': 'returns',
|
||||
'member': 'memberof'
|
||||
'member': 'memberof',
|
||||
'overview': 'file',
|
||||
'fileoverview':'file'
|
||||
}
|
||||
|
||||
//TODO: move into a shared module?
|
||||
|
||||
88
modules/jsdoc/tagdictionary.js
Normal file
88
modules/jsdoc/tagdictionary.js
Normal file
@ -0,0 +1,88 @@
|
||||
/**
|
||||
@overview Provides information about the various differnt types of tags.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
/** */
|
||||
exports.TagDictionary = {};
|
||||
exports.TagDictionary.lookUp = function(tagTitle) {
|
||||
return this['@'+tagTitle] || {};
|
||||
}
|
||||
exports.TagDictionary.synonyms = {
|
||||
};
|
||||
|
||||
/** */
|
||||
function TagDefinition(tagTitle, opts) {
|
||||
this.title = tagTitle;
|
||||
|
||||
this.isIsa = false; // the name of this tag is used to define the doclet's isa property
|
||||
this.canProvideName = false; // this tag can be used to name the doclet
|
||||
this.isDocspace = false; // The name of this tag becomes the docspace for the doclet name, like event:
|
||||
this.canHaveType = false; // this tag can have a {type}
|
||||
this.canHavePname = false; // this tag can have a parameter-type name
|
||||
this.canHavePdesc = false;
|
||||
this.keepsWhitespace = false;
|
||||
|
||||
for (var p in opts) {
|
||||
if (typeof opts[p] !== 'undefined') {
|
||||
this[p] = opts[p];
|
||||
}
|
||||
}
|
||||
|
||||
exports.TagDictionary['@'+tagTitle] = this;
|
||||
}
|
||||
// event handlers?
|
||||
TagDefinition.prototype.onDoclet = function(tag, doclet) {
|
||||
if (this.isIsa) {
|
||||
if (doclet.isa) {
|
||||
throw 'Overwriting isa: "'+doclet.isa+'" with "'+this.title+'"';
|
||||
}
|
||||
doclet.isa = this.title;
|
||||
}
|
||||
|
||||
if (this.canProvideName) {
|
||||
if (doclet.isa) {
|
||||
throw 'Overwriting isa: "'+doclet.isa+'" with "'+this.title+'"';
|
||||
}
|
||||
doclet.isa = this.title;
|
||||
}
|
||||
}
|
||||
|
||||
new TagDefinition('namespace', {
|
||||
isIsa: true,
|
||||
canProvideName: true
|
||||
});
|
||||
|
||||
new TagDefinition('constructor', {
|
||||
isIsa: true,
|
||||
canProvideName: true
|
||||
});
|
||||
|
||||
new TagDefinition('file', {
|
||||
isIsa: true,
|
||||
canProvideName: true,
|
||||
isDocspace: true
|
||||
});
|
||||
|
||||
new TagDefinition('event', {
|
||||
isIsa: true,
|
||||
canProvideName: true,
|
||||
isDocspace: true
|
||||
});
|
||||
|
||||
new TagDefinition('example', {
|
||||
keepsWhitespace: true
|
||||
});
|
||||
|
||||
new TagDefinition('param', {
|
||||
canHaveType: true,
|
||||
canHavePname: true,
|
||||
canHavePdesc: true
|
||||
});
|
||||
|
||||
new TagDefinition('returns', {
|
||||
canHaveType: true,
|
||||
canHavePdesc: true
|
||||
});
|
||||
|
||||
})();
|
||||
@ -11,37 +11,37 @@
|
||||
(function() {
|
||||
|
||||
/**
|
||||
@param {string} tagText
|
||||
@param {string} tagValue
|
||||
@returns {Array.<string>}
|
||||
*/
|
||||
exports.parse = function(tagText) {
|
||||
if (typeof tagText !== 'string') { tagText = ''; }
|
||||
exports.parse = function(tagValue) {
|
||||
if (typeof tagValue !== 'string') { tagValue = ''; }
|
||||
var type = '',
|
||||
text = '',
|
||||
count = 0;
|
||||
|
||||
// type expressions start with '{'
|
||||
if (tagText[0] === '{') {
|
||||
if (tagValue[0] === '{') {
|
||||
count++;
|
||||
|
||||
// find matching closer '}'
|
||||
for (var i = 1, leni = tagText.length; i < leni; i++) {
|
||||
if (tagText[i] === '{') { count++; }
|
||||
else if (tagText[i] === '}') { count--; }
|
||||
for (var i = 1, leni = tagValue.length; i < leni; i++) {
|
||||
if (tagValue[i] === '{') { count++; }
|
||||
else if (tagValue[i] === '}') { count--; }
|
||||
|
||||
if (count === 0) {
|
||||
type = trim(tagText.slice(1, i));
|
||||
text = trim(tagText.slice(i+1));
|
||||
type = trim(tagValue.slice(1, i));
|
||||
text = trim(tagValue.slice(i+1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type === '') { text = tagText; }
|
||||
if (type === '') { text = tagValue; }
|
||||
|
||||
[type, optional] = parseOptional(type);
|
||||
[type, nullable] = parseNullable(type);
|
||||
|
||||
|
||||
type = parseTypes(type); // make it into an array
|
||||
|
||||
return [type, text, optional, nullable];
|
||||
@ -87,7 +87,7 @@
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
|
||||
/** @private */
|
||||
function trim(text) {
|
||||
return text.replace(/^\s+|\s+$/g, '');
|
||||
|
||||
@ -10,6 +10,10 @@ load(BASEDIR + '/test/tests/11_tag_namespace.js');
|
||||
load(BASEDIR + '/test/tests/12_tag_property.js');
|
||||
load(BASEDIR + '/test/tests/13_tag_method.js');
|
||||
load(BASEDIR + '/test/tests/14_tag_member.js');
|
||||
load(BASEDIR + '/test/tests/15_tag_type.js');
|
||||
load(BASEDIR + '/test/tests/16_tag_return.js');
|
||||
|
||||
load(BASEDIR + '/test/tests/20_tag_file.js');
|
||||
|
||||
// see http://visionmedia.github.com/jspec/
|
||||
JSpec.run({
|
||||
|
||||
18
test/samples/tag_constructor.js
Normal file
18
test/samples/tag_constructor.js
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
/**
|
||||
@name Foo
|
||||
@constructor
|
||||
*/
|
||||
|
||||
/**
|
||||
@constructor Bar
|
||||
*/
|
||||
|
||||
|
||||
/** @constructor */
|
||||
function Pez() {
|
||||
}
|
||||
|
||||
/** @constructor */
|
||||
Qux = function() {
|
||||
}
|
||||
21
test/samples/tag_file_1.js
Normal file
21
test/samples/tag_file_1.js
Normal file
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @fileoverview This file is to be used for testing the JSDoc parser
|
||||
* It is not intended to be an example of good JavaScript OO-programming,
|
||||
* nor is it intended to fulfill any specific purpose apart from
|
||||
* demonstrating the functionality of the
|
||||
* {@link http://sourceforge.net/projects/jsdoc JSDoc} parser
|
||||
*
|
||||
* @author Michael Mathews <micmath@gmail.com>
|
||||
* @version 0.1
|
||||
*/
|
||||
|
||||
function Shape(){
|
||||
|
||||
this.getClassName = function(){
|
||||
return "Shape";
|
||||
}
|
||||
|
||||
function addReference(){
|
||||
// Do nothing...
|
||||
}
|
||||
}
|
||||
@ -16,7 +16,7 @@
|
||||
expect(doclet.constructor.name).to(eql, 'Doclet');
|
||||
});
|
||||
|
||||
it('should have a `tagText` method', function() {
|
||||
it('should have a `tagValue` method', function() {
|
||||
expect(doclet).to(respond_to, 'toObject');
|
||||
});
|
||||
|
||||
@ -35,20 +35,20 @@
|
||||
});
|
||||
});
|
||||
|
||||
describe('The returned value of jsdoc.Doclet#tagText', function() {
|
||||
describe('The returned value of jsdoc.Doclet#tagValue', function() {
|
||||
it('should be a string', function() {
|
||||
var returnedValue = doclet.tagText('name');
|
||||
var returnedValue = doclet.tagValue('name');
|
||||
expect(returnedValue).to(be_a, String);
|
||||
});
|
||||
|
||||
it('should be the text of the tag that matches the given tag name', function() {
|
||||
var returnedValue = doclet.tagText('name');
|
||||
var returnedValue = doclet.tagValue('name');
|
||||
expect(returnedValue).to(eql, 'Foo');
|
||||
});
|
||||
|
||||
it('should be the text of the last tag that matches the given tag name if there are more than 1', function() {
|
||||
var returnedValue = doclet.tagText('param');
|
||||
expect(returnedValue).to(eql, 'b');
|
||||
it('should be the text of the first tag that matches the given tag name if there are more than 1', function() {
|
||||
var returnedValue = doclet.tagValue('param');
|
||||
expect(returnedValue).to(eql, 'a');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -19,8 +19,8 @@
|
||||
expect(jsdoc.tag).to(be_an, Object);
|
||||
});
|
||||
|
||||
it('should have a `fromTagText` method', function() {
|
||||
expect(jsdoc.tag).to(respond_to, 'fromTagText');
|
||||
it('should have a `fromText` method', function() {
|
||||
expect(jsdoc.tag).to(respond_to, 'fromText');
|
||||
});
|
||||
|
||||
it('should have a `parse` method', function() {
|
||||
@ -48,8 +48,7 @@
|
||||
|
||||
it('should have a `text` property which is an string', function() {
|
||||
var tag = tags[0];
|
||||
expect(tag).to(have_property, 'text');
|
||||
expect(tag.text).to(be_an, String);
|
||||
expect(tag).to(have_property, 'value');
|
||||
});
|
||||
|
||||
it('should have a `type` property which is an array', function() {
|
||||
@ -73,10 +72,10 @@
|
||||
});
|
||||
});
|
||||
|
||||
describe('The tag#text property', function() {
|
||||
describe('The tag#value property', function() {
|
||||
it('should be set to the text after the @name', function() {
|
||||
var tag = tags[0];
|
||||
expect(tag.text).to(eql, 'Hello world');
|
||||
expect(tag.value).to(eql, 'Hello world');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -10,51 +10,51 @@
|
||||
tag: require('jsdoc/tag'),
|
||||
parser: require('jsdoc/parser')
|
||||
};
|
||||
jsdoc.parser.parseFiles(BASEDIR + 'test/tests/10_tag_constructor.js');
|
||||
jsdoc.parser.parseFiles(BASEDIR + 'test/samples/tag_constructor.js');
|
||||
doclets = jsdoc.parser.result;
|
||||
});
|
||||
|
||||
describe('A doclet from a constructor tag with a name tag and no code', function() {
|
||||
it('should have an `isa` property set to "constructor"', function() {
|
||||
var doclet = doclets[0].toObject();
|
||||
expect(doclet).to(have_property, 'isa');
|
||||
expect(doclet.isa).to(eql, 'constructor');
|
||||
});
|
||||
|
||||
it('should have a `name` property set to the given name"', function() {
|
||||
var doclet = doclets[0].toObject();
|
||||
expect(doclet).to(have_property, 'name');
|
||||
expect(doclet.name).to(eql, 'Foo');
|
||||
});
|
||||
});
|
||||
|
||||
describe('A doclet from a named constructor tag and no code', function() {
|
||||
it('should have an `isa` property set to "constructor"', function() {
|
||||
var doclet = doclets[1].toObject();
|
||||
expect(doclet).to(have_property, 'isa');
|
||||
expect(doclet.isa).to(eql, 'constructor');
|
||||
});
|
||||
|
||||
it('should have a `name` property set to the given name"', function() {
|
||||
var doclet = doclets[1].toObject();
|
||||
expect(doclet).to(have_property, 'name');
|
||||
expect(doclet.name).to(eql, 'Bar');
|
||||
});
|
||||
});
|
||||
|
||||
describe('A doclet from a constructor tag and named code', function() {
|
||||
it('should have an `isa` property set to "constructor"', function() {
|
||||
var doclet = doclets[2].toObject();
|
||||
expect(doclet).to(have_property, 'isa');
|
||||
expect(doclet.isa).to(eql, 'constructor');
|
||||
});
|
||||
|
||||
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, 'Pez');
|
||||
});
|
||||
});
|
||||
describe('A doclet from a constructor tag with a name tag and no code', function() {
|
||||
it('should have an `isa` property set to "constructor"', function() {
|
||||
var doclet = doclets[0].toObject();
|
||||
expect(doclet).to(have_property, 'isa');
|
||||
expect(doclet.isa).to(eql, 'constructor');
|
||||
});
|
||||
|
||||
it('should have a `name` property set to the given name"', function() {
|
||||
var doclet = doclets[0].toObject();
|
||||
expect(doclet).to(have_property, 'name');
|
||||
expect(doclet.name).to(eql, 'Foo');
|
||||
});
|
||||
});
|
||||
|
||||
describe('A doclet from a named constructor tag and no code', function() {
|
||||
it('should have an `isa` property set to "constructor"', function() {
|
||||
var doclet = doclets[1].toObject();
|
||||
expect(doclet).to(have_property, 'isa');
|
||||
expect(doclet.isa).to(eql, 'constructor');
|
||||
});
|
||||
|
||||
it('should have a `name` property set to the given name"', function() {
|
||||
var doclet = doclets[1].toObject();
|
||||
expect(doclet).to(have_property, 'name');
|
||||
expect(doclet.name).to(eql, 'Bar');
|
||||
});
|
||||
});
|
||||
|
||||
describe('A doclet from a constructor tag and named code', function() {
|
||||
it('should have an `isa` property set to "constructor"', function() {
|
||||
var doclet = doclets[2].toObject();
|
||||
expect(doclet).to(have_property, 'isa');
|
||||
expect(doclet.isa).to(eql, 'constructor');
|
||||
});
|
||||
|
||||
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, 'Pez');
|
||||
});
|
||||
});
|
||||
|
||||
describe('A doclet from a constructor tag and named anonymous function', function() {
|
||||
it('should have an `isa` property set to "constructor"', function() {
|
||||
@ -71,28 +71,4 @@
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
||||
|
||||
(function testarea() {
|
||||
|
||||
/**
|
||||
@name Foo
|
||||
@constructor
|
||||
*/
|
||||
|
||||
/**
|
||||
@constructor Bar
|
||||
*/
|
||||
|
||||
/**
|
||||
@constructor
|
||||
*/
|
||||
function Pez() {
|
||||
}
|
||||
|
||||
/**
|
||||
@constructor
|
||||
*/
|
||||
Qux = function() {
|
||||
}
|
||||
})();
|
||||
@ -11,47 +11,60 @@
|
||||
parser: require('jsdoc/parser')
|
||||
};
|
||||
jsdoc.parser.parseFiles(BASEDIR + 'test/tests/14_tag_member.js');
|
||||
doclets = jsdoc.parser.result;
|
||||
doclets = jsdoc.parser.result.map(function($){ return $.toObject(); });
|
||||
|
||||
});
|
||||
|
||||
describe('A doclet with a method tag and a memberof tag', function() {
|
||||
it('should have an `isa` property set to "method"', function() {
|
||||
var doclet = doclets[2].toObject();
|
||||
var doclet = doclets[2];
|
||||
expect(doclet).to(have_property, 'isa');
|
||||
expect(doclet.isa).to(eql, 'method');
|
||||
});
|
||||
|
||||
it('should have a `name` property set to the given name"', function() {
|
||||
var doclet = doclets[2].toObject();
|
||||
var doclet = doclets[2];
|
||||
expect(doclet).to(have_property, 'name');
|
||||
expect(doclet.name).to(eql, 'fah');
|
||||
});
|
||||
|
||||
it('should have a `memberof` property set to the given member name', function() {
|
||||
var doclet = doclets[2].toObject();
|
||||
var doclet = doclets[2];
|
||||
expect(doclet).to(have_property, 'memberof');
|
||||
expect(doclet.memberof).to(eql, 'foo');
|
||||
expect(doclet.memberof).to(eql, 'foo#');
|
||||
});
|
||||
|
||||
it('should have a `path` property set to the parent+member names', function() {
|
||||
var doclet = doclets[2];
|
||||
expect(doclet).to(have_property, 'path');
|
||||
expect(doclet.path).to(eql, 'foo#fah');
|
||||
});
|
||||
});
|
||||
|
||||
describe('A doclet with a property tag and a member tag', function() {
|
||||
it('should have an `isa` property set to "property"', function() {
|
||||
var doclet = doclets[3].toObject();
|
||||
var doclet = doclets[3];
|
||||
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();
|
||||
var doclet = doclets[3];
|
||||
expect(doclet).to(have_property, 'name');
|
||||
expect(doclet.name).to(eql, 'bah');
|
||||
});
|
||||
|
||||
it('should have a `memberof` property set to the given member name', function() {
|
||||
var doclet = doclets[3].toObject();
|
||||
var doclet = doclets[3];
|
||||
expect(doclet).to(have_property, 'memberof');
|
||||
expect(doclet.memberof).to(eql, 'bar');
|
||||
});
|
||||
|
||||
it('should have a `path` property set to the parent+member names', function() {
|
||||
var doclet = doclets[3];
|
||||
expect(doclet).to(have_property, 'path');
|
||||
expect(doclet.path).to(eql, 'bar.bah');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@ -65,7 +78,7 @@
|
||||
|
||||
/**
|
||||
@method fah
|
||||
@memberof foo
|
||||
@memberof foo#
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
67
test/tests/15_tag_type.js
Normal file
67
test/tests/15_tag_type.js
Normal file
@ -0,0 +1,67 @@
|
||||
(function() {
|
||||
var jsdoc,
|
||||
doclets;
|
||||
|
||||
JSpec.describe('@type', function() {
|
||||
|
||||
before(function() {
|
||||
// docsets can only be created by parsers
|
||||
jsdoc = {
|
||||
tag: require('jsdoc/tag'),
|
||||
parser: require('jsdoc/parser')
|
||||
};
|
||||
jsdoc.parser.parseFiles(BASEDIR + 'test/tests/15_tag_type.js');
|
||||
|
||||
doclets = jsdoc.parser.result.map(function($){ return $.toObject(); });
|
||||
});
|
||||
|
||||
describe('A doclet with a type tag whose value is a simple string like "number"', function() {
|
||||
it('should have an `type` property set to string "number"', function() {
|
||||
var doclet = doclets[2];
|
||||
expect(doclet).to(have_property, 'type');
|
||||
expect(doclet.type).to(eql, 'number');
|
||||
});
|
||||
});
|
||||
|
||||
describe('A doclet with a type tag whose value is a series of piped strings like "number | Array.<number>"', function() {
|
||||
it('should have an `type` property set to [number, Array.<number>]', function() {
|
||||
var doclet = doclets[3];
|
||||
expect(doclet).to(have_property, 'type');
|
||||
|
||||
expect(doclet.type).to(eql, ['number', 'Array.<number>']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('A doclet with a type tag whose value contains braces like "{number|function(string:a, string:b){}:number}"', function() {
|
||||
it('should have an `type` property set to [number, Array.<number>]', function() {
|
||||
var doclet = doclets[4];
|
||||
expect(doclet).to(have_property, 'type');
|
||||
|
||||
expect(doclet.type).to(eql, ['number', 'function(string:a, string:b){}:number']);
|
||||
});
|
||||
});
|
||||
});
|
||||
})();
|
||||
|
||||
(function testarea() {
|
||||
|
||||
/** @namespace foo */
|
||||
|
||||
/** @constructor bar */
|
||||
|
||||
/**
|
||||
@property foo#fah
|
||||
@type number
|
||||
*/
|
||||
|
||||
/**
|
||||
@property foo#fahfah
|
||||
@type number | Array.<number>
|
||||
*/
|
||||
|
||||
/**
|
||||
@property bar.bah
|
||||
@type {number|function(string:a, string:b){}:number}
|
||||
*/
|
||||
|
||||
})();
|
||||
69
test/tests/16_tag_return.js
Normal file
69
test/tests/16_tag_return.js
Normal file
@ -0,0 +1,69 @@
|
||||
(function() {
|
||||
var jsdoc,
|
||||
doclets;
|
||||
|
||||
JSpec.describe('@return', function() {
|
||||
|
||||
before(function() {
|
||||
// docsets can only be created by parsers
|
||||
jsdoc = {
|
||||
tag: require('jsdoc/tag'),
|
||||
parser: require('jsdoc/parser')
|
||||
};
|
||||
jsdoc.parser.parseFiles(BASEDIR + 'test/tests/16_tag_return.js');
|
||||
|
||||
doclets = jsdoc.parser.result.map(function($){ return $.toObject(); });
|
||||
});
|
||||
|
||||
describe('A doclet with a returns tag whose value has a type and desc', function() {
|
||||
it('should have an `returns` property', function() {
|
||||
var doclet = doclets[0];
|
||||
expect(doclet).to(have_property, 'returns');
|
||||
});
|
||||
});
|
||||
|
||||
describe('The returns value of that doclet', function() {
|
||||
it('should have an `type` property set to the given type', function() {
|
||||
var returns = doclets[0].returns;
|
||||
expect(returns).to(have_property, 'type');
|
||||
expect(returns.type).to(eql, ['number']);
|
||||
});
|
||||
|
||||
it('should have an `desc` property set to the given desc', function() {
|
||||
var returns = doclets[0].returns;
|
||||
expect(returns).to(have_property, 'desc');
|
||||
expect(returns.desc).to(eql, 'The size of the foo.');
|
||||
});
|
||||
});
|
||||
|
||||
describe('A doclet with a (synonym) return tag whose value has a desc', function() {
|
||||
it('should have an `returns` property', function() {
|
||||
var doclet = doclets[1];
|
||||
expect(doclet).to(have_property, 'returns');
|
||||
});
|
||||
});
|
||||
|
||||
describe('The returns value of that doclet', function() {
|
||||
it('should have an `desc` property set to the given desc', function() {
|
||||
var returns = doclets[1].returns;
|
||||
expect(returns).to(have_property, 'desc');
|
||||
expect(returns.desc).to(eql, 'So a horse walks into a....');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
||||
|
||||
(function testarea() {
|
||||
|
||||
/**
|
||||
@function foo
|
||||
@returns {number} The size of the foo.
|
||||
*/
|
||||
|
||||
/**
|
||||
@function bar
|
||||
@return So a horse walks into a....
|
||||
*/
|
||||
|
||||
})();
|
||||
32
test/tests/20_tag_file.js
Normal file
32
test/tests/20_tag_file.js
Normal file
@ -0,0 +1,32 @@
|
||||
(function() {
|
||||
var jsdoc,
|
||||
doclets;
|
||||
|
||||
JSpec.describe('@file', function() {
|
||||
|
||||
before(function() {
|
||||
// docsets can only be created by parsers
|
||||
jsdoc = {
|
||||
tag: require('jsdoc/tag'),
|
||||
parser: require('jsdoc/parser')
|
||||
};
|
||||
jsdoc.parser.parseFiles(BASEDIR + 'test/samples/tag_file_1.js');
|
||||
|
||||
doclets = jsdoc.parser.result.map(function($){ return $.toObject(); });
|
||||
});
|
||||
|
||||
describe('A doclet with a fileoverview tag and no name tag', function() {
|
||||
it('should have an `isa` property set to "file"', function() {
|
||||
var doclet = doclets[0];
|
||||
expect(doclet).to(have_property, 'isa');
|
||||
expect(doclet.isa).to(eql, 'file');
|
||||
});
|
||||
|
||||
it('should have an `name` property set to a string equal to the files name', function() {
|
||||
var doclet = doclets[0];
|
||||
expect(doclet).to(have_property, 'name');
|
||||
expect(doclet.name).to(match, /test\/samples\/tag_file_1\.js$/);
|
||||
});
|
||||
});
|
||||
});
|
||||
})();
|
||||
Loading…
x
Reference in New Issue
Block a user