diff --git a/lib/jsdoc/tag.js b/lib/jsdoc/tag.js index 32808562..b7b479cf 100644 --- a/lib/jsdoc/tag.js +++ b/lib/jsdoc/tag.js @@ -66,10 +66,14 @@ exports.Tag = function(tagTitle, tagBody, meta) { var tagType = jsdoc.tag.type.parse(this.text, tagDef.canHaveName, tagDef.canHaveType); - if (tagType.type && tagType.type.length) { - this.value.type = { - names: tagType.type - }; + // BUG: a tag can *not* have a type but still have optional, nullable, variable, defaultvalue. + // e.g. @param [foo] has name 'foo' and property optional=true but *no type*. + if (tagType.type) { + if (tagType.type.length) { + this.value.type = { + names: tagType.type + }; + } this.value.optional = tagType.optional; this.value.nullable = tagType.nullable; this.value.variable = tagType.variable; diff --git a/test/fixtures/paramtag.js b/test/fixtures/paramtag.js index db431bfc..c6fd831c 100644 --- a/test/fixtures/paramtag.js +++ b/test/fixtures/paramtag.js @@ -39,3 +39,9 @@ function split(delimiter) { */ function commit(atomic) { } + +/** + * @param [async=true] - whether to be asynchronous + */ +function request(async) { +} diff --git a/test/specs/jsdoc/tag.js b/test/specs/jsdoc/tag.js index e40a55a5..52d6938a 100644 --- a/test/specs/jsdoc/tag.js +++ b/test/specs/jsdoc/tag.js @@ -24,6 +24,7 @@ describe("jsdoc/tag", function() { ' * myFunction(1, 2); // returns 3\n' + ' * myFunction(3, 4); // returns 7\n'; var tagArg = new jsdoc.tag.Tag('arg ', text, meta), // <-- a symonym of param, space in the title. + tagParam = new jsdoc.tag.Tag('param', '[foo=1]', meta), // no type, but has optional and defaultvalue. tagEg = new jsdoc.tag.Tag('example', textEg, meta), // <-- for keepsWhitespace tagType = new jsdoc.tag.Tag('type', 'MyType ', meta); // <-- for onTagText @@ -101,15 +102,18 @@ describe("jsdoc/tag", function() { expect(tag.value[prop]).toEqual(info[prop]); } } - expect(tag.value.type).toBeDefined(); - expect(typeof tag.value.type).toEqual('object'); - expect(tag.value.type.names).toBeDefined(); - expect(tag.value.type.names).toEqual(info.type); + if (info.type && info.type.length) { + expect(tag.value.type).toBeDefined(); + expect(typeof tag.value.type).toEqual('object'); + expect(tag.value.type.names).toBeDefined(); + expect(tag.value.type.names).toEqual(info.type); + } } it("if the tag has a type, tag.value should contain the type information", function() { // we assume jsdoc/tag/type.parse works (it has its own tests to verify this); verifyTagType(tagType); verifyTagType(tagArg); + verifyTagType(tagParam); }); it("if the tag has a description beyond the name/type, this should be in tag.value.description", function() { diff --git a/test/specs/jsdoc/tag/type.js b/test/specs/jsdoc/tag/type.js index 5f985b33..c9953133 100644 --- a/test/specs/jsdoc/tag/type.js +++ b/test/specs/jsdoc/tag/type.js @@ -122,6 +122,10 @@ describe("jsdoc/tag/type", function() { desc = "{string=} [foo]"; info = jsdoc.tag.type.parse(desc, true, true); expect(info.optional).toEqual(true); + + desc = "[foo]"; + info = jsdoc.tag.type.parse(desc, true, true); + expect(info.optional).toEqual(true); }); it("should return the types as an array", function() { diff --git a/test/specs/tags/paramtag.js b/test/specs/tags/paramtag.js index 14d628ad..b0e1046c 100644 --- a/test/specs/tags/paramtag.js +++ b/test/specs/tags/paramtag.js @@ -6,7 +6,8 @@ describe("@param tag", function() { getElement = docSet.getByLongname('getElement')[0], combine = docSet.getByLongname('combine')[0], split = docSet.getByLongname('split')[0], - commit = docSet.getByLongname('commit')[0]; + commit = docSet.getByLongname('commit')[0], + request = docSet.getByLongname('request')[0]; it('When a symbol has an @param tag with a type before the name, the doclet has a params property that includes that param.', function() { expect(typeof find.params).toEqual('object'); @@ -62,7 +63,18 @@ describe("@param tag", function() { expect(commit.params[0].description).toEqual('If true make the commit atomic.'); }); + it('When a symbol has a @param tag with no type but a name that indicates a default value or optional type, this infor is copied over to the params property.', function() { + expect(typeof request.params).toEqual('object'); + expect(request.params.length).toEqual(1); + expect(request.params[0].type).toBeUndefined(); + expect(request.params[0].name).toBe('async'); + expect(request.params[0].defaultvalue).toBe('true'); + expect(request.params[0].optional).toBe(true); + expect(request.params[0].description).toEqual('whether to be asynchronous'); + }); + it('When a symbol has an @param tag with no name and a name is given in the code, the doclet has a params property that includes that param with the name from the code.', function() { expect(commit.params[0].name).toEqual('atomic'); }); -}); \ No newline at end of file + +});