From d7e74062b1400ed6bf99b3ec4c7ea1382fc7a1ef Mon Sep 17 00:00:00 2001 From: Michael Mathews Date: Sun, 20 Nov 2011 22:12:51 +0000 Subject: [PATCH] Fixed issue that caused members of named function statements to have the wrong memberof attributes generated by the parser. Closes Issue #60. --- rhino_modules/jsdoc/src/parser.js | 26 ++++++++++++------- test/cases/namedFuncStatement.js | 7 +++++ test/cases/namedFuncStatement2.js | 7 +++++ test/cases/namedFuncStatement3.js | 9 +++++++ test/runner.js | 1 + test/t/cases/namedFuncStatement.js | 41 ++++++++++++++++++++++++++++++ 6 files changed, 82 insertions(+), 9 deletions(-) create mode 100644 test/cases/namedFuncStatement.js create mode 100644 test/cases/namedFuncStatement2.js create mode 100644 test/cases/namedFuncStatement3.js create mode 100644 test/t/cases/namedFuncStatement.js diff --git a/rhino_modules/jsdoc/src/parser.js b/rhino_modules/jsdoc/src/parser.js index 091e938f..fc78bb52 100644 --- a/rhino_modules/jsdoc/src/parser.js +++ b/rhino_modules/jsdoc/src/parser.js @@ -143,7 +143,7 @@ function pretreat(code) { exports.Parser.prototype.astnodeToMemberof = function(node) { var memberof = {}; - if (node.type === Token.VAR || node.type === Token.FUNCTION) { + if (node.type === Token.VAR || node.type === Token.FUNCTION || node.type == tkn.NAMEDFUNCTIONTATEMENT) { if (node.enclosingFunction) { // an inner var or func memberof.id = 'astnode'+node.enclosingFunction.hashCode(); memberof.doclet = this.refs[memberof.id]; @@ -170,9 +170,10 @@ exports.Parser.prototype.resolveThis = function(node) { var memberof = {}; if (node.type !== Token.COLON && node.enclosingFunction) { + // get documentation for the enclosing function memberof.id = 'astnode'+node.enclosingFunction.hashCode(); memberof.doclet = this.refs[memberof.id]; - + if (!memberof.doclet) { return ''; // TODO handle global this? } @@ -342,7 +343,7 @@ function visitNode(node) { astnode: node, code: aboutNode(node) }; - + // keep track of vars in a function scope if (node.enclosingFunction) { var func = 'astnode'+node.enclosingFunction.hashCode(), @@ -362,7 +363,7 @@ function visitNode(node) { currentParser.refs['astnode'+e.code.node.hashCode()] = e.doclet; // allow lookup from value => doclet } } - else if (node.type == Token.FUNCTION) { + else if (node.type == Token.FUNCTION || node.type == tkn.NAMEDFUNCTIONTATEMENT) { e = { id: 'astnode'+node.hashCode(), // the id of the COLON node comment: String(node.jsDoc||'@undocumented'), @@ -372,8 +373,8 @@ function visitNode(node) { code: aboutNode(node) }; - e.code.name = String(node.name) || ''; - + e.code.name = (node.type == tkn.NAMEDFUNCTIONTATEMENT)? '' : String(node.name) || ''; +//console.log(':: e.code.name is '+e.code.name); // keep track of vars in a function scope if (node.enclosingFunction) { var func = 'astnode'+node.enclosingFunction.hashCode(), @@ -418,7 +419,7 @@ function parserFactory() { ce.initFromContext(cx); return new Packages.org.mozilla.javascript.Parser(ce, ce.getErrorReporter()); } - +var tkn = { NAMEDFUNCTIONTATEMENT: -1001 }; /** * Attempts to find the name and type of the given node. * @private @@ -427,8 +428,8 @@ function parserFactory() { function aboutNode(node) { about = {}; - if (node.type == Token.FUNCTION) { - about.name = '' + node.name; + if (node.type == Token.FUNCTION || node.type == tkn.NAMEDFUNCTIONTATEMENT) { + about.name = node.type == tkn.NAMEDFUNCTIONTATEMENT? '' : '' + node.name; about.type = 'function'; about.node = node; } @@ -438,6 +439,9 @@ function aboutNode(node) { about.node = node.initializer; about.value = nodeToString(about.node); about.type = getTypeName(node.initializer); + if (about.type === 'FUNCTION' && about.node.name) { + about.node.type = tkn.NAMEDFUNCTIONTATEMENT; + } } else { // like var i; about.node = node.target; @@ -457,6 +461,10 @@ function aboutNode(node) { about.node = node.right; about.value = nodeToString(about.node); about.type = getTypeName(node.right); + + if (about.type === 'FUNCTION' && about.node.name) { + about.node.type = tkn.NAMEDFUNCTIONTATEMENT; + } } else { // type 39 (NAME) diff --git a/test/cases/namedFuncStatement.js b/test/cases/namedFuncStatement.js new file mode 100644 index 00000000..924a659f --- /dev/null +++ b/test/cases/namedFuncStatement.js @@ -0,0 +1,7 @@ +/** @class */ +var Foo = function Bar(a) { + /** document me */ + var var1 = 1; + /** document me */ + this.member1 = 2; +}; diff --git a/test/cases/namedFuncStatement2.js b/test/cases/namedFuncStatement2.js new file mode 100644 index 00000000..0223092a --- /dev/null +++ b/test/cases/namedFuncStatement2.js @@ -0,0 +1,7 @@ +/** @class */ +Foo = function Bar(a) { + /** document me */ + var var1 = 1; + /** document me */ + this.member1 = 2; +}; diff --git a/test/cases/namedFuncStatement3.js b/test/cases/namedFuncStatement3.js new file mode 100644 index 00000000..8f185816 --- /dev/null +++ b/test/cases/namedFuncStatement3.js @@ -0,0 +1,9 @@ +ns = { + /** @class */ + Foo: function Bar(a) { + /** document me */ + var var1 = 1; + /** document me */ + this.member1 = 2; + } +}; \ No newline at end of file diff --git a/test/runner.js b/test/runner.js index f76504a2..ae341fed 100644 --- a/test/runner.js +++ b/test/runner.js @@ -143,6 +143,7 @@ testFile('test/t/cases/memberoftag3.js'); testFile('test/t/cases/memberoftagforced.js'); testFile('test/t/cases/moduletag.js'); testFile('test/t/cases/moduletag2.js'); +testFile('test/t/cases/namedFuncStatement.js'); testFile('test/t/cases/paramtag.js'); testFile('test/t/cases/privatetag.js'); testFile('test/t/cases/quotename.js'); diff --git a/test/t/cases/namedFuncStatement.js b/test/t/cases/namedFuncStatement.js new file mode 100644 index 00000000..00cfc6a1 --- /dev/null +++ b/test/t/cases/namedFuncStatement.js @@ -0,0 +1,41 @@ +(function() { + var docSet = testhelpers.getDocSetFromFile('test/cases/namedFuncStatement.js'), + fooMember = docSet.getByLongname('Foo#member1')[0], + fooVariable = docSet.getByLongname('Foo~var1')[0]; + //console.log(docSet); + test('A symbol that is a member of a named function statement.', function() { + assert.equal(fooMember.longname, 'Foo#member1', 'is documented as a member of the assigned name.'); + }); + + test('A symbol that is a variable of a named function statement.', function() { + assert.equal(fooVariable.longname, 'Foo~var1', 'is documented as a variable of the assigned name.'); + }); +})(); + +(function() { + var docSet = testhelpers.getDocSetFromFile('test/cases/namedFuncStatement2.js'), + fooMember = docSet.getByLongname('Foo#member1')[0], + fooVariable = docSet.getByLongname('Foo~var1')[0]; + //console.log(docSet); + test('A symbol that is a member of a named function statement.', function() { + assert.equal(fooMember.longname, 'Foo#member1', 'is documented as a member of the assigned name.'); + }); + + test('A symbol that is a variable of a named function statement.', function() { + assert.equal(fooVariable.longname, 'Foo~var1', 'is documented as a variable of the assigned name.'); + }); +})(); + +(function() { + var docSet = testhelpers.getDocSetFromFile('test/cases/namedFuncStatement3.js'), + fooMember = docSet.getByLongname('ns.Foo#member1')[0], + fooVariable = docSet.getByLongname('ns.Foo~var1')[0]; + //console.log(docSet); + test('A symbol that is a member of a named function statement.', function() { + assert.equal(fooMember.longname, 'ns.Foo#member1', 'is documented as a member of the assigned name.'); + }); + + test('A symbol that is a variable of a named function statement.', function() { + assert.equal(fooVariable.longname, 'ns.Foo~var1', 'is documented as a variable of the assigned name.'); + }); +})(); \ No newline at end of file