From 8840f30a0bededeb2dca70e8c4e22e8fb1234ab1 Mon Sep 17 00:00:00 2001 From: Jeff Williams Date: Fri, 20 Jun 2014 16:51:36 -0700 Subject: [PATCH] autodetect parameter names in function expressions (#674) --- lib/jsdoc/src/astnode.js | 5 +++- test/fixtures/paramtag.js | 8 ++++++ test/fixtures/paramtag2.js | 7 +++++ test/specs/tags/paramtag.js | 54 ++++++++++++++++++++++++++----------- 4 files changed, 57 insertions(+), 17 deletions(-) create mode 100644 test/fixtures/paramtag2.js diff --git a/lib/jsdoc/src/astnode.js b/lib/jsdoc/src/astnode.js index 5799b3f3..4127f19e 100644 --- a/lib/jsdoc/src/astnode.js +++ b/lib/jsdoc/src/astnode.js @@ -258,12 +258,15 @@ var getInfo = exports.getInfo = function(node) { var info = {}; switch (node.type) { - // like: "foo = 'bar'" (after foo has been declared) + // like: "foo = 'bar'" (after declaring foo) + // like: "MyClass.prototype.myMethod = function() {}" (after declaring MyClass) case Syntax.AssignmentExpression: info.node = node.right; info.name = nodeToString(node.left); info.type = info.node.type; info.value = nodeToString(info.node); + // if the assigned value is a function, we need to capture the parameter names here + info.paramnames = getParamNames(node.right); break; // like: "function foo() {}" diff --git a/test/fixtures/paramtag.js b/test/fixtures/paramtag.js index c6fd831c..247fdc99 100644 --- a/test/fixtures/paramtag.js +++ b/test/fixtures/paramtag.js @@ -45,3 +45,11 @@ function commit(atomic) { */ function request(async) { } + +/** @class */ +function MySocket() {} +/** + * @param {string} - Hostname. + * @param {number} - Port number. + */ +MySocket.prototype.open = function(hostname, port) {}; diff --git a/test/fixtures/paramtag2.js b/test/fixtures/paramtag2.js new file mode 100644 index 00000000..7b5d3f97 --- /dev/null +++ b/test/fixtures/paramtag2.js @@ -0,0 +1,7 @@ +/** @module mysocket */ + +/** + * @param {string} - Hostname. + * @param {number} - Port number. + */ +exports.open = function(hostname, port) {}; diff --git a/test/specs/tags/paramtag.js b/test/specs/tags/paramtag.js index c72ddc40..7953735d 100644 --- a/test/specs/tags/paramtag.js +++ b/test/specs/tags/paramtag.js @@ -1,16 +1,13 @@ -/*global describe: true, env: true, expect: true, it: true, jasmine: true, spyOn: true */ -describe("@param tag", function() { - var docSet = jasmine.getDocSetFromFile('test/fixtures/paramtag.js'), - find = docSet.getByLongname('find')[0], - unbind = docSet.getByLongname('unbind')[0], - bind = docSet.getByLongname('bind')[0], - getElement = docSet.getByLongname('getElement')[0], - combine = docSet.getByLongname('combine')[0], - split = docSet.getByLongname('split')[0], - commit = docSet.getByLongname('commit')[0], - request = docSet.getByLongname('request')[0]; +/*global describe, expect, it, jasmine */ +'use strict'; + +describe('@param tag', function() { + var docSet = jasmine.getDocSetFromFile('test/fixtures/paramtag.js'); + var docSet2 = jasmine.getDocSetFromFile('test/fixtures/paramtag2.js'); 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() { + var find = docSet.getByLongname('find')[0]; + expect(typeof find.params).toBe('object'); expect(find.params.length).toBe(1); expect(find.params[0].type.names.join(', ')).toBe('String, Array.'); @@ -19,6 +16,8 @@ describe("@param tag", function() { }); it('When a symbol has an @param tag with only a type and name, the doclet has a params property that includes that param.', function() { + var bind = docSet.getByLongname('bind')[0]; + expect(typeof bind.params).toBe('object'); expect(bind.params.length).toBe(1); expect(bind.params[0].type.names.join(', ')).toBe('function'); @@ -27,6 +26,8 @@ describe("@param tag", function() { }); it('When a symbol has an @param tag with only a type, the doclet has a params property that includes that param.', function() { + var unbind = docSet.getByLongname('unbind')[0]; + expect(typeof unbind.params).toBe('object'); expect(unbind.params.length).toBe(1); expect(unbind.params[0].type.names.join(', ')).toBe('function'); @@ -34,6 +35,8 @@ describe("@param tag", function() { }); it('When a symbol has an @param tag with no type, the doclet has a params property that includes that param.', function() { + var getElement = docSet.getByLongname('getElement')[0]; + expect(typeof getElement.params).toBe('object'); expect(getElement.params.length).toBe(1); expect(getElement.params[0].type).toBeUndefined(); @@ -42,6 +45,8 @@ describe("@param tag", function() { }); it('When a symbol has an @param tag with a non-alpha name like "...", the doclet has a params property that includes that param.', function() { + var combine = docSet.getByLongname('combine')[0]; + expect(typeof combine.params).toBe('object'); expect(combine.params.length).toBe(1); expect(combine.params[0].type).toBeUndefined(); @@ -50,6 +55,8 @@ describe("@param tag", function() { }); it('When a symbol has an @param tag with name followed by a dash, the doclet has a params property that includes that param.', function() { + var split = docSet.getByLongname('split')[0]; + expect(typeof split.params).toBe('object'); expect(split.params.length).toBe(1); expect(split.params[0].type).toBeUndefined(); @@ -58,6 +65,8 @@ describe("@param tag", function() { }); it('When a symbol has an @param tag with no name or type, the doclet has a params property that includes that param.', function() { + var commit = docSet.getByLongname('commit')[0]; + expect(typeof commit.params).toBe('object'); expect(commit.params.length).toBe(1); expect(commit.params[0].type).toBeUndefined(); @@ -65,6 +74,8 @@ describe("@param tag", function() { }); it('When a symbol has a @param tag with no type but a name that indicates a default value or optional type, this is copied over to the params property.', function() { + var request = docSet.getByLongname('request')[0]; + expect(typeof request.params).toBe('object'); expect(request.params.length).toBe(1); expect(request.params[0].type).toBeUndefined(); @@ -74,15 +85,26 @@ describe("@param tag", function() { expect(request.params[0].description).toBe('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() { + it('When a symbol has a @param tag with no name, the doclet includes the param name from the code', function() { + var commit = docSet.getByLongname('commit')[0]; + expect(commit.params[0].name).toBe('atomic'); }); + it('When a symbol has a @param tag with no name, and the symbol is part of an assignment expression, the doclet includes the param name from the code', function() { + var classOpen = docSet.getByLongname('MySocket#open')[0]; + var moduleOpen = docSet2.getByLongname('module:mysocket.open')[0]; + + expect(classOpen.params[0].name).toBe('hostname'); + expect(classOpen.params[1].name).toBe('port'); + + expect(moduleOpen.params[0].name).toBe('hostname'); + expect(moduleOpen.params[1].name).toBe('port'); + }); + it('When a symbol has a @param tag with an invalid type expression, the JSDoc comment is ignored.', function() { - var badDocSet; - var test; - badDocSet = jasmine.getDocSetFromFile('test/fixtures/paramtaginvalidtype.js'); - test = badDocSet.getByLongname('Test#test')[0]; + var badDocSet = jasmine.getDocSetFromFile('test/fixtures/paramtaginvalidtype.js'); + var test = badDocSet.getByLongname('Test#test')[0]; expect(test).toBeDefined(); expect(typeof test).toBe('object');