diff --git a/node_modules/common/args.js b/node_modules/common/args.js index efb56ae4..bbef8152 100644 --- a/node_modules/common/args.js +++ b/node_modules/common/args.js @@ -39,12 +39,14 @@ * @param {string} longName The equivalent long name of the option, entered like: --test. * @param {boolean} hasValue Does this option require a value? Like: -t templatename * @param {string} helpText + * @param {function} [coercer] A function to coerce the given value to a specific type. * @example * myParser.addOption('t', 'template', true, 'The path to the template.'); * myParser.addOption('h', 'help', false, 'Show the help message.'); */ - exports.ArgParser.prototype.addOption = function(shortName, longName, hasValue, helpText, canHaveMultiple) { - this._options.push({shortName: shortName, longName: longName, hasValue: hasValue, helpText: helpText, canHaveMultiple: (canHaveMultiple || false)}); + exports.ArgParser.prototype.addOption = function(shortName, longName, hasValue, helpText, canHaveMultiple, coercer) { + this._options.push({shortName: shortName, longName: longName, hasValue: hasValue, helpText: helpText, canHaveMultiple: (canHaveMultiple || false), coercer: coercer}); + if (shortName) { this._shortNameIndex[shortName] = this._options.length - 1; } @@ -133,15 +135,23 @@ } else { value = true; + if (next && next.charAt(0) !== '-') { + throw new Error( 'Command line option does not allow a value: ' + name ); + } } if (option.longName && shortName) { name = option.longName; } + if (typeof option.coercer === 'function') { + value = option.coercer(value); + } + // Allow for multiple options of the same type to be present if (option.canHaveMultiple && hasOwnProperty.call(result, name)) { var val = result[name]; + if (val instanceof Array) { val.push(value); } else { diff --git a/rhino_modules/jsdoc/opts/parser.js b/rhino_modules/jsdoc/opts/parser.js index 03839914..c1cbefc4 100644 --- a/rhino_modules/jsdoc/opts/parser.js +++ b/rhino_modules/jsdoc/opts/parser.js @@ -12,8 +12,7 @@ var common = { var argParser = new common.args.ArgParser(), ourOptions, defaults = { - destination: './out/', - strict: true + destination: './out/' }; argParser.addOption('t', 'template', true, 'The name of the template to use. Default: the "default" template'); @@ -23,7 +22,7 @@ argParser.addOption('T', 'test', false, 'Run all tests and quit.'); argParser.addOption('d', 'destination', true, 'The path to the output folder. Use "console" to dump data to the console. Default: console'); argParser.addOption('p', 'private', false, 'Display symbols marked with the @private tag. Default: false.'); argParser.addOption('r', 'recurse', false, 'Recurse into subdirectories when scanning for source code files.'); -argParser.addOption('s', 'strict', false, 'Exit immediately if a doclet is incomplete or contains errors. Default: true'); +argParser.addOption('l', 'lenient', false, 'Continue to generate output if a doclet is incomplete or contains errors. Default: false.'); argParser.addOption('h', 'help', false, 'Print this message and quit.'); argParser.addOption('X', 'explain', false, 'Dump all found doclet internals to console and quit.'); argParser.addOption('q', 'query', true, 'Provide a querystring to define custom variable names/values to add to the options hash.'); diff --git a/rhino_modules/jsdoc/tag.js b/rhino_modules/jsdoc/tag.js index 28251201..583862df 100644 --- a/rhino_modules/jsdoc/tag.js +++ b/rhino_modules/jsdoc/tag.js @@ -87,15 +87,15 @@ exports.Tag = function(tagTitle, tagBody, meta) { } } - // validate the tag. for strict validation, throw an exception; otherwise, log a warning. + // 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.strict) { - throw e; - } else { + if (env.opts.lenient) { console.log(e); + } else { + throw e; } } } diff --git a/test/specs/common/args.js b/test/specs/common/args.js new file mode 100644 index 00000000..e12836c9 --- /dev/null +++ b/test/specs/common/args.js @@ -0,0 +1,41 @@ +describe("common/args", function() { + var common = {args: require('common/args')}, + argParser = new common.args.ArgParser(), + ourOptions; + + function trueFalse(v) { + var r = false; + if (v) { + if (v === 'true') { r = true; } + else if (v === 'false') { r = false; } + else { v = !!r; } + } + + return r; + } + + argParser.addOption('s', 'strict', true, 'Throw error on invalid input.', false, trueFalse); + argParser.addOption('n', 'name', true, 'The name of the project.'); + + ourOptions = argParser.parse(['-s', 'true', '-n', 'true']); + + it('should corece a true value if a coercer is provided', function() { + expect(ourOptions.strict).toBeDefined(); + expect(ourOptions.strict).toEqual(true); + }); + + it('should corece a string value if a no coercer is provided', function() { + expect(ourOptions.name).toBeDefined(); + expect(ourOptions.name).toEqual('true'); + }); + + function doParse() { + argParser.addOption('b', 'debug', false, 'Use debug mode.'); + argParser.parse(['-b', 'yesplease']); + } + + it('should throw an error if an option does not accept a value and one is given', function() { + expect(doParse).toThrow(); + }); + +}); \ No newline at end of file diff --git a/test/specs/jsdoc/tag.js b/test/specs/jsdoc/tag.js index e2624338..eb701fab 100644 --- a/test/specs/jsdoc/tag.js +++ b/test/specs/jsdoc/tag.js @@ -8,31 +8,29 @@ describe("jsdoc/tag", function() { return tag; } - it("has strict validation enabled by default", function() { + it("is strict, not lenient, by default", function() { expect(badTag).toThrow(); }); - it("throws an exception for bad tags if strict validation is enabled", function() { - var strict = !!env.opts.strict; - - env.opts.strict = true; + 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.strict = strict; + env.opts.lenient = lenient; }); - it("doesn't throw an exception for bad tags if strict validation is disabled", function() { + it("doesn't throw an exception for bad tags if the lenient option is enabled", function() { /*jshint evil: true */ - var strict = !!env.opts.strict, - log = new Function(console.log); - + var lenient = !!env.opts.lenient, + log = eval(console.log); console.log = function() {}; - env.opts.strict = false; + env.opts.lenient = true; expect(badTag).not.toThrow(); - env.opts.strict = strict; + env.opts.lenient = lenient; console.log = log; }); }); \ No newline at end of file