Merge branch 'master' into type-refactor

This commit is contained in:
Jeff Williams 2012-08-18 09:03:55 -07:00
commit c643a6a1b9
19 changed files with 315 additions and 50 deletions

View File

@ -96,7 +96,8 @@ var doop = require("jsdoc/util/doop").doop;
this.visited[key] = true;
if (!(key in this.dependencies)) {
throw new Error("Missing dependency: " + key);
require('jsdoc/util/error').handle( new Error("Missing dependency: " + key) );
return;
}
for (var path in this.dependencies[key]) {
if ( hasOwnProp.call(this.dependencies[key], path) ) {

View File

@ -123,7 +123,7 @@ function pretreat(code) {
// merge adjacent doclets
.replace(/\*\/\/\*\*+/g, '@also')
// make lent objectliterals documentable by giving them a dummy name
.replace(/(\/\*\*[^\*\/]*?@lends\b[^\*\/]*?\*\/\s*)\{/g, '$1 ____ = {') // like return @lends {
.replace(/(\/\*\*[^\*\/]*?[\*\s]*@lends\s(?:[^\*]|\*(?!\/))*\*\/\s*)\{/g, '$1 ____ = {') // like return @lends {
.replace(/(\/\*\*[^\*\/]*?@lends\b[^\*\/]*?\*\/)(\s*)return(\s*)\{/g, '$2$3 return $1 ____ = {'); // like @lends return {
}

View File

@ -95,15 +95,5 @@ exports.Tag = function(tagTitle, tagBody, meta) {
}
}
// validate the tag. in lenient mode, log a warning; otherwise, throw an exception.
try {
jsdoc.tag.validator.validate(this, meta);
}
catch (e) {
if (env.opts.lenient) {
console.log(e);
} else {
throw e;
}
}
jsdoc.tag.validator.validate(this, meta);
};

View File

@ -35,17 +35,17 @@ exports.validate = function(tag, meta) {
var tagDef = dictionary.lookUp(tag.title);
if (!tagDef && !env.conf.tags.allowUnknownTags) {
throw new UnknownTagError(tag.title, meta);
require('jsdoc/util/error').handle( new UnknownTagError(tag.title, meta) );
}
if (!tag.text) {
if (tagDef.mustHaveValue) {
throw new TagValueRequiredError(tag.title, meta);
require('jsdoc/util/error').handle( new TagValueRequiredError(tag.title, meta) );
}
}
else {
if (tagDef.mustNotHaveValue) {
throw new TagValueNotPermittedError(tag.title, meta);
require('jsdoc/util/error').handle( new TagValueNotPermittedError(tag.title, meta) );
}
}
};

View File

@ -32,7 +32,7 @@ exports.root = new tutorial.Tutorial('', '');
/** Additional instance method for root node.
@param {string} name - Tutorial name.
@reutrn {tutorial.Tutorial} Tutorial instance.
@return {tutorial.Tutorial} Tutorial instance.
*/
exports.root.getByName = function(name) {
return tutorials[name];
@ -93,7 +93,6 @@ exports.load = function(path) {
};
/** Resolves hierarchical structure.
@param {object} map - Contents map.
*/
exports.resolve = function() {
var item,
@ -118,13 +117,12 @@ exports.resolve = function() {
// add children
if (item.children) {
item.children.forEach(function(child) {
// I really didn't want to throw you an exception in most cases
// but now, user, you pissed me off ;)
if (!(child in tutorials)) {
throw new Error("Missing child tutorial: " + child);
require('jsdoc/util/error').handle( new Error("Missing child tutorial: " + child) );
}
else {
tutorials[child].setParent(current);
}
tutorials[child].setParent(current);
});
}
}

View File

@ -0,0 +1,32 @@
/*global env: true */
/**
Helper functions for handling errors.
@module jsdoc/util/error
*/
/**
Handle an exception appropriately based on whether lenient mode is enabled:
+ If lenient mode is enabled, log the exception to the console.
+ If lenient mode is not enabled, re-throw the exception.
@param {Error} e - The exception to handle.
@exception {Error} Re-throws the original exception unless lenient mode is enabled.
@memberof module:jsdoc/util/error
*/
exports.handle = function(e) {
var msg;
if (env.opts.lenient) {
msg = e.message || JSON.stringify(e);
// include the error type if it's an Error object
if (e instanceof Error) {
msg = e.constructor.name + ": " + msg;
}
console.log(msg);
}
else {
throw e;
}
};

View File

@ -65,6 +65,7 @@ exports.registerLink = function(longname, url) {
function toLink(longname, content) {
if (!longname) {
// if this happens, there's something wrong with the caller itself; the user can't fix this
throw new Error('Missing required parameter: url');
}
@ -96,7 +97,8 @@ function toLink(longname, content) {
var toTutorial = exports.toTutorial = function(tutorial, content) {
if (!tutorial) {
throw new Error('Missing required parameter: tutorial');
require('jsdoc/util/error').handle( new Error('Missing required parameter: tutorial') );
return;
}
var node = tutorials.getByName(tutorial);
@ -155,7 +157,8 @@ exports.tutorialToUrl = function(tutorial) {
var node = tutorials.getByName(tutorial);
// no such tutorial
if (!node) {
throw new Error('No such tutorial: '+tutorial);
require('jsdoc/util/error').handle( new Error('No such tutorial: '+tutorial) );
return;
}
return 'tutorial-'+strToFilename(node.name)+exports.fileExtension;

6
test/fixtures/augmentstag2.js vendored Normal file
View File

@ -0,0 +1,6 @@
// Test for @augments tags that refer to undefined symbols
/**
* @constructor
* @extends Foo
*/
function Bar() {}

18
test/fixtures/lends3.js vendored Normal file
View File

@ -0,0 +1,18 @@
/** @class */
var Person = makeClass(
/**
* @lends Person#
*/
{
/** Set up initial values. */
initialize: function(name) {
/** The name of the person. */
this.name = name;
},
/** Speak a message. */
say: function(message) {
return this.name + " says: " + message;
}
}
);

View File

@ -34,6 +34,20 @@ describe("lends", function() {
});
});
describe("case that uses @lends in a multiline doclet", function() {
var docSet = jasmine.getDocSetFromFile('test/fixtures/lends3.js'),
init = docSet.getByLongname('Person#initialize'),
name = docSet.getByLongname('Person#name');
it("The member should be documented as a member of the lendee", function() {
expect(init.length, 1);
});
it("The this member should be documented as a member of the lendee", function() {
expect(name.length, 1);
});
});
});
describe("when a documented member is inside an objlit associated with a @lends tag that has no value.", function() {

View File

@ -1,3 +1,31 @@
/*global describe: true, env: true, it: true */
describe("jsdoc/augment", function() {
//TODO
});
/*jshint evil: true */
// TODO: more tests
var lenient = !!env.opts.lenient,
log = eval(console.log);
function augmentMissingSymbol() {
var badDocSet = jasmine.getDocSetFromFile('test/fixtures/augmentstag2.js');
}
afterEach(function() {
env.opts.lenient = lenient;
console.log = log;
});
it("throws an error for missing dependencies if the lenient option is not enabled", function() {
env.opts.lenient = false;
expect(augmentMissingSymbol).toThrow();
});
it("does not throw an error for missing dependencies if the lenient option is enabled", function() {
console.log = function() {};
env.opts.lenient = true;
expect(augmentMissingSymbol).not.toThrow();
});
});

View File

@ -1,6 +1,11 @@
/*global describe: true, env: true, it: true */
describe("jsdoc/tag", function() {
/*jshint evil: true */
// TODO: more tests
var lenient = !!env.opts.lenient,
log = eval(console.log);
function badTag() {
var Tag = require("jsdoc/tag").Tag;
@ -8,29 +13,21 @@ describe("jsdoc/tag", function() {
return tag;
}
it("is strict, not lenient, by default", function() {
expect(badTag).toThrow();
});
it("throws an exception for bad tags if the lenient option is not enabled", function() {
var lenient = !!env.opts.lenient;
env.opts.lenient = false;
expect(badTag).toThrow();
env.opts.lenient = lenient;
});
it("doesn't throw an exception for bad tags if the lenient option is enabled", function() {
/*jshint evil: true */
var lenient = !!env.opts.lenient,
log = eval(console.log);
console.log = function() {};
env.opts.lenient = true;
expect(badTag).not.toThrow();
afterEach(function() {
env.opts.lenient = lenient;
console.log = log;
});
it("throws an exception for bad tags if the lenient option is not enabled", function() {
env.opts.lenient = false;
expect(badTag).toThrow();
});
it("doesn't throw an exception for bad tags if the lenient option is enabled", function() {
console.log = function() {};
env.opts.lenient = true;
expect(badTag).not.toThrow();
});
});

View File

@ -0,0 +1,4 @@
/*global describe: true, env: true, it: true */
describe("jsdoc/tutorial", function() {
//TODO
});

View File

@ -0,0 +1,33 @@
/*global describe: true, env: true, it: true */
describe("jsdoc/tutorial/resolver", function() {
/*jshint evil: true */
// TODO: more tests
var resolver = require('jsdoc/tutorial/resolver'),
lenient = !!env.opts.lenient,
log = eval(console.log);
function missingTutorial() {
resolver.load(env.dirname + "/test/tutorials/incomplete");
resolver.resolve();
}
afterEach(function() {
env.opts.lenient = lenient;
console.log = log;
});
it("throws an exception for missing tutorials if the lenient option is not enabled", function() {
env.opts.lenient = false;
expect(missingTutorial).toThrow();
});
it("doesn't throw an exception for missing tutorials if the lenient option is enabled", function() {
console.log = function() {};
env.opts.lenient = true;
expect(missingTutorial).not.toThrow();
});
});

View File

@ -0,0 +1,4 @@
/*global describe: true, it: true */
describe("jsdoc/util/doop", function() {
// TODO
});

View File

@ -0,0 +1,55 @@
/*global describe: true, env: true, it: true */
describe("jsdoc/util/error", function() {
var error = require('jsdoc/util/error'),
handle = error.handle;
it("should exist", function() {
expect(error).toBeDefined();
expect(typeof error).toEqual("object");
});
it("should export a 'handle' function", function() {
expect(handle).toBeDefined();
expect(typeof handle).toEqual("function");
});
describe("handle", function() {
/*jshint evil: true */
var lenient = !!env.opts.lenient,
log = eval(console.log);
function handleError() {
handle( new Error("foo") );
}
function handleObject() {
handle( { foo: "bar", baz: "qux"} );
}
afterEach(function() {
env.opts.lenient = lenient;
console.log = log;
});
it("should re-throw errors by default", function() {
expect(handleError).toThrow();
});
it("should re-throw errors if lenient mode is not enabled", function() {
env.opts.lenient = false;
expect(handleError).toThrow();
});
it("should not re-throw errors if lenient mode is enabled", function() {
env.opts.lenient = true;
console.log = function() {};
expect(handleError).not.toThrow();
});
it("should still work if the 'e' param is not an instanceof Error", function() {
expect(handleObject).toThrow();
});
});
});

View File

@ -1,3 +1,4 @@
/*global describe: true, env: true, it: true */
describe("jsdoc/util/templateHelper", function() {
var helper = require('jsdoc/util/templateHelper');
helper.registerLink('test', 'path/to/test.html');
@ -137,5 +138,82 @@ describe("jsdoc/util/templateHelper", function() {
});
});
//TODO: tests for tutorial functions?
xdescribe("registerLink", function() {
// TODO
});
xdescribe("longnameToUrl", function() {
// TODO
});
xdescribe("setTutorials", function() {
// TODO
});
describe("toTutorial", function() {
/*jshint evil: true */
// TODO: more tests
var lenient = !!env.opts.lenient,
log = eval(console.log);
function missingParam() {
helper.toTutorial();
}
afterEach(function() {
env.opts.lenient = lenient;
console.log = log;
});
it('throws an exception if the first param is missing and the lenient option is not enabled', function() {
env.opts.lenient = false;
expect(missingParam).toThrow();
});
it('does not throw an exception if the first param is missing and the lenient option is enabled', function() {
console.log = function() {};
env.opts.lenient = true;
expect(missingParam).not.toThrow();
});
});
describe("tutorialToUrl", function() {
/*jshint evil: true */
// TODO: more tests
var lenient = !!env.opts.lenient,
log = eval(console.log);
function missingTutorial() {
var url = helper.tutorialToUrl("be-a-perfect-person-in-just-three-days");
}
beforeEach(function() {
var root = require('jsdoc/tutorial/resolver').root;
helper.setTutorials(root);
});
afterEach(function() {
helper.setTutorials(null);
env.opts.lenient = lenient;
console.log = log;
});
it('throws an exception if the tutorial is missing and the lenient option is not enabled', function() {
env.opts.lenient = false;
expect(missingTutorial).toThrow();
});
it('does not throw an exception if the tutorial is missing and the lenient option is enabled', function() {
console.log = function() {};
env.opts.lenient = true;
expect(missingTutorial).not.toThrow();
});
});
});

View File

@ -0,0 +1,3 @@
<h1>Test.html</h1>
<p>{@link Test}</p>

View File

@ -0,0 +1 @@
{"title": "missing child tutorial", "children": ["test2"]}