Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ output:
"type": "method",
"receiver": "exports",
"name": "escape",
"params": [ "html" ],
"string": "exports.escape()"
}
}
Expand Down
41 changes: 32 additions & 9 deletions lib/dox.js
Original file line number Diff line number Diff line change
Expand Up @@ -508,82 +508,89 @@ exports.contextPatternMatchers = [

function (str, parentContext) {
// class constructor
if (/^\s*constructor\s*\(/.exec(str)) {
if (/^\s*constructor\s*\(([\w,\s$_]*)\)/.exec(str)) {
return {
type: 'constructor'
, constructor: parentContext.name
, cons: parentContext.name
, name: 'constructor'
, params: splitParams(RegExp.$1)
, string: (parentContext && parentContext.name && parentContext.name + '.prototype.' || '') + 'constructor()'
};
// class method
}
},

function (str, parentContext) {
if (/^\s*(static)?\s*(\*)?\s*([\w$]+|\[.*\])\s*\(/.exec(str)) {
if (/^\s*(static)?\s*(\*)?\s*([\w$]+|\[.*\])\s*\(([\w,\s$_]*)\)/.exec(str)) {
return {
type: 'method'
, constructor: parentContext.name
, cons: parentContext.name
, name: RegExp.$2 + RegExp.$3
, params: splitParams(RegExp.$4)
, string: (parentContext && parentContext.name && parentContext.name + (RegExp.$1 ? '.' : '.prototype.') || '') + RegExp.$2 + RegExp.$3 + '()'
};
// named function statement, possibly exported by name or as a default
}
},

function (str) {
if (/^\s*(export(\s+default)?\s+)?function\s+([\w$]+)\s*\(/.exec(str)) {
if (/^\s*(export(\s+default)?\s+)?function\s+([\w$]+)\s*\(([\w,\s$_]*)\)/.exec(str)) {
return {
type: 'function'
, name: RegExp.$3
, params: splitParams(RegExp.$4)
, string: RegExp.$3 + '()'
};
}
},

function (str) {
// anonymous function expression exported as a default
if (/^\s*export\s+default\s+function\s*\(/.exec(str)) {
if (/^\s*export\s+default\s+function\s*\(([\w,\s$_]*)\)/.exec(str)) {
return {
type: 'function'
, name: RegExp.$1 // undefined
, params: splitParams(RegExp.$2)
, string: RegExp.$1 + '()'
};
}
},

function (str) {
// function expression
if (/^return\s+function(?:\s+([\w$]+))?\s*\(/.exec(str)) {
if (/^return\s+function(?:\s+([\w$]+))?\s*\(([\w,\s$_]*)\)/.exec(str)) {
return {
type: 'function'
, name: RegExp.$1
, params: splitParams(RegExp.$2)
, string: RegExp.$1 + '()'
};
}
},

function (str) {
// function expression
if (/^\s*(?:const|let|var)\s+([\w$]+)\s*=\s*function/.exec(str)) {
if (/^\s*(?:const|let|var)\s+([\w$]+)\s*=\s*function(?:\s+([\w$]+))?\s*\(([\w,\s$_]*)\)/.exec(str)) {
return {
type: 'function'
, name: RegExp.$1
, params: splitParams(RegExp.$3)
, string: RegExp.$1 + '()'
};
}
},

function (str, parentContext) {
// prototype method
if (/^\s*([\w$.]+)\s*\.\s*prototype\s*\.\s*([\w$]+)\s*=\s*function/.exec(str)) {
if (/^\s*([\w$.]+)\s*\.\s*prototype\s*\.\s*([\w$]+)\s*=\s*function(?:\s+([\w$]+))?\s*\(([\w,\s$_]*)\)/.exec(str)) {
return {
type: 'method'
, constructor: RegExp.$1
, cons: RegExp.$1
, name: RegExp.$2
, params: splitParams(RegExp.$4)
, string: RegExp.$1 + '.prototype.' + RegExp.$2 + '()'
};
}
Expand Down Expand Up @@ -631,12 +638,13 @@ exports.contextPatternMatchers = [

function (str, parentContext) {
// inline method
if (/^\s*([\w$.]+)\s*:\s*function/.exec(str)) {
if (/^\s*([\w$.]+)\s*:\s*function(?:\s+([\w$]+))?\s*\(([\w,\s$_]*)\)/.exec(str)) {
return {
type: 'method'
, constructor: parentContext.name
, cons: parentContext.name
, name: RegExp.$1
, params: splitParams(RegExp.$3)
, string: (parentContext && parentContext.name && parentContext.name + '.prototype.' || '') + RegExp.$1 + '()'
};
}
Expand Down Expand Up @@ -671,11 +679,12 @@ exports.contextPatternMatchers = [

function (str) {
// method
if (/^\s*([\w$.]+)\s*\.\s*([\w$]+)\s*=\s*function/.exec(str)) {
if (/^\s*([\w$.]+)\s*\.\s*([\w$]+)\s*=\s*function(?:\s+([\w$]+))?\s*\(([\w,\s$_]*)\)/.exec(str)) {
return {
type: 'method'
, receiver: RegExp.$1
, name: RegExp.$2
, params: splitParams(RegExp.$4)
, string: RegExp.$1 + '.' + RegExp.$2 + '()'
};
}
Expand Down Expand Up @@ -706,3 +715,17 @@ exports.contextPatternMatchers = [
}
}
];

/**
* Split the signature-part of a function/method/constructor into a list of param names
* @param {string} signature
* @return {string[]} list of params
*/
function splitParams (signature) {
if (signature.length === 0) {
return [];
}
return signature.split(',').map(function(param) {
return param.trim()
});
}
4 changes: 4 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
console.log(`getFirst: function getFirstBarItem(){
return this.bar[0];
}
`.match(/^\s*([\w$.]+)\s*:\s*function(.*)/))
36 changes: 30 additions & 6 deletions test/dox.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ module.exports = {
var parseComments = comments.shift();
parseComments.tags.should.have.length(4);
parseComments.ctx.type.should.equal('method');
parseComments.ctx.params.should.eql(['js'])
parseComments.ctx.receiver.should.equal('exports');
parseComments.ctx.name.should.equal('parseComments');
parseComments.description.full.should.equal('<p>Parse comments in the given string of <code>js</code>.</p>');
Expand Down Expand Up @@ -161,6 +162,7 @@ module.exports = {
first.ctx.type.should.equal('method');
first.ctx.receiver.should.equal('exports');
first.ctx.name.should.equal('parseTagTypes');
first.ctx.params.should.eql(['str'])
first.code.should.equal('exports.parseTagTypes = function(str) {\n\treturn str\n\t\t.replace(/[{}]/g, \'\')\n\t\t.split(/ *[|,\\/] */);\n};');
first.line.should.equal(2);
first.codeStart.should.equal(11);
Expand All @@ -180,6 +182,7 @@ module.exports = {
first.ctx.type.should.equal('method');
first.ctx.receiver.should.equal('exports');
first.ctx.name.should.equal('parseTagTypes');
first.ctx.params.should.eql(['str'])
first.code.should.equal('exports.parseTagTypes = function(str) {\n return str\n .replace(/[{}]/g, \'\')\n .split(/ *[|,\\/] */);\n};');
first.line.should.equal(2);
first.codeStart.should.equal(11);
Expand All @@ -199,6 +202,7 @@ module.exports = {
first.ctx.type.should.equal('method');
first.ctx.receiver.should.equal('exports');
first.ctx.name.should.equal('parseTagTypes');
first.ctx.params.should.eql(['str']);
first.code.should.equal('exports.parseTagTypes = function(str) {\n\treturn str\n\t\t.replace(/[{}]/g, \'\')\n\t\t.split(/ *[|,\\/] */);\n};');
first.line.should.equal(2);
first.codeStart.should.equal(11);
Expand Down Expand Up @@ -231,6 +235,7 @@ module.exports = {
comments[2].description.full.should.equal('<p>A method of an instance of Foo</p>');
comments[2].ctx.type.should.be.equal('method');
comments[2].ctx.name.should.be.equal('method');
comments[2].ctx.params.should.eql([]);
comments[2].ctx.string.should.be.equal('Foo.prototype.method()');
comments[2].line.should.equal(18);
comments[2].codeStart.should.equal(22);
Expand Down Expand Up @@ -260,6 +265,7 @@ module.exports = {
comments[1].description.full.should.equal('<p>construct a Foo</p>');
comments[1].ctx.type.should.be.equal('constructor');
comments[1].ctx.name.should.be.equal('constructor');
comments[1].ctx.params.should.eql(['options']);
comments[1].ctx.constructor.should.be.equal('FooBar');
comments[1].ctx.string.should.be.equal('FooBar.prototype.constructor()');
comments[1].line.should.equal(9);
Expand All @@ -268,6 +274,7 @@ module.exports = {
// class method
comments[2].description.full.should.equal('<p>Method of the Foo class.</p>');
comments[2].ctx.type.should.be.equal('method');
comments[2].ctx.params.should.eql([]);
comments[2].ctx.name.should.be.equal('bar');
comments[2].ctx.constructor.should.be.equal('FooBar');
comments[2].ctx.string.should.be.equal('FooBar.prototype.bar()');
Expand All @@ -277,6 +284,7 @@ module.exports = {
// class static method
comments[3].description.full.should.equal('<p>Static method of the Foo class.</p>');
comments[3].ctx.type.should.be.equal('method');
comments[3].ctx.params.should.eql([]);
comments[3].ctx.name.should.be.equal('staticMethod');
comments[3].ctx.constructor.should.be.equal('FooBar');
comments[3].ctx.string.should.be.equal('FooBar.staticMethod()');
Expand All @@ -287,6 +295,7 @@ module.exports = {
comments[4].description.full.should.equal('<p>Static generator method of the Foo class.</p>');
comments[4].ctx.type.should.be.equal('method');
comments[4].ctx.name.should.be.equal('*staticGeneratorMethod');
comments[4].ctx.params.should.eql([]);
comments[4].ctx.constructor.should.be.equal('FooBar');
comments[4].ctx.string.should.be.equal('FooBar.*staticGeneratorMethod()');
comments[4].line.should.equal(34);
Expand All @@ -295,6 +304,7 @@ module.exports = {
// class generator method with computed name
comments[5].description.full.should.equal('<p>Generator method with computed name.</p>');
comments[5].ctx.type.should.be.equal('method');
comments[5].ctx.params.should.eql([]);
comments[5].ctx.name.should.be.equal('*[Symbol.iterator]');
comments[5].ctx.constructor.should.be.equal('FooBar');
comments[5].ctx.string.should.be.equal('FooBar.prototype.*[Symbol.iterator]()');
Expand Down Expand Up @@ -333,6 +343,7 @@ module.exports = {
comments[9].description.full.should.equal('');
comments[9].ctx.type.should.be.equal('constructor');
comments[9].ctx.name.should.be.equal('constructor');
comments[9].ctx.params.should.eql(['options']);
comments[9].ctx.constructor.should.be.equal('Baz');
comments[9].ctx.string.should.be.equal('Baz.prototype.constructor()');
comments[9].line.should.equal(72);
Expand Down Expand Up @@ -373,6 +384,7 @@ module.exports = {
comments[0].description.full.should.equal('<p>Luke, I am your constructor.</p>');
comments[0].ctx.type.should.be.equal('constructor');
comments[0].ctx.name.should.be.equal('Foo');
comments[0].ctx.params.should.eql(['bar']);
comments[0].ctx.string.should.be.equal('Foo()');

// prototoype object
Expand All @@ -385,6 +397,7 @@ module.exports = {
comments[2].description.full.should.equal('<p>Returns the first item.</p>');
comments[2].ctx.type.should.be.equal('method');
comments[2].ctx.name.should.be.equal('getFirst');
comments[2].ctx.params.should.eql([]);
comments[2].ctx.string.should.be.equal('Foo.prototype.getFirst()');

// getter function
Expand All @@ -403,6 +416,7 @@ module.exports = {
comments[5].description.full.should.equal('<p>Anonymous function on property.</p>');
comments[5].ctx.type.should.be.equal('method');
comments[5].ctx.name.should.be.equal('random');
comments[5].ctx.params.should.eql([]);
comments[5].ctx.string.should.be.equal('Foo.prototype.random()');

// this should be a separated function
Expand All @@ -413,6 +427,7 @@ module.exports = {
// classical prototype function property
comments[7].description.full.should.equal('<p>Returns the last item.</p>\n<pre><code class="lang-javascript">var f = new Foo([1, 5, 10]);\n\nf.getLast() === 10;\n</code></pre>');
comments[7].ctx.type.should.be.equal('method');
comments[7].ctx.params.should.eql([]);
comments[7].ctx.name.should.be.equal('getLast');
comments[7].ctx.string.should.be.equal('Foo.prototype.getLast()');

Expand Down Expand Up @@ -443,12 +458,14 @@ module.exports = {
comments[2].description.full.should.equal('<p>This function surely does something</p>');
comments[2].ctx.type.should.be.equal('method');
comments[2].ctx.name.should.be.equal('doSomething');
comments[2].ctx.params.should.eql([]);
comments[2].ctx.string.should.be.equal('doSomething()');

// property as a named method function
comments[3].description.full.should.equal('<p>And them something else</p>');
comments[3].ctx.type.should.be.equal('method');
comments[3].ctx.name.should.be.equal('doSomethingElse');
comments[3].ctx.params.should.eql([]);
comments[3].ctx.string.should.be.equal('doSomethingElse()');

// getter function
Expand All @@ -473,6 +490,7 @@ module.exports = {
first.ctx.type.should.equal('method');
first.ctx.receiver.should.equal('exports');
first.ctx.name.should.equal('parseTagTypes');
first.ctx.params.should.eql(['str']);
first.code.should.equal('exports.parseTagTypes = function(str) {\n return str\n .replace(/[{}]/g, \'\')\n .split(/ *[|,\\/] */);\n};');
first.line.should.equal(2);
first.codeStart.should.equal(11);
Expand Down Expand Up @@ -528,33 +546,38 @@ module.exports = {
},

'test .parseCodeContext() function statement': function(){
var ctx = dox.parseCodeContext('function $foo(){\n\n}');
var ctx = dox.parseCodeContext('function $foo(a,b){\n\n}');
ctx.type.should.equal('function');
ctx.params.should.eql(['a','b']);
ctx.name.should.equal('$foo');
},

'test .parseCodeContext() returned unnamed function statement': function(){
var ctx = dox.parseCodeContext('return function (){\n\n}');
var ctx = dox.parseCodeContext('return function ( a , b ){\n\n}');
ctx.type.should.equal('function');
ctx.params.should.eql(['a','b']);
ctx.name.should.equal('');
},

'test .parseCodeContext() returned named function statement': function(){
var ctx = dox.parseCodeContext('return function $foo (){\n\n}');
var ctx = dox.parseCodeContext('return function $foo (a$,b$){\n\n}');
ctx.type.should.equal('function');
ctx.params.should.eql(['a$','b$']);
ctx.name.should.equal('$foo');
},

'test .parseCodeContext() function expression': function(){
var ctx = dox.parseCodeContext('var $foo = function(){\n\n}');
var ctx = dox.parseCodeContext('var $foo = function(_a\t, \t_b){\n\n}');
ctx.type.should.equal('function');
ctx.params.should.eql(['_a','_b']);
ctx.name.should.equal('$foo');
},

'test .parseCodeContext() prototype method': function(){
var ctx = dox.parseCodeContext('$User.prototype.$save = function(){}');
var ctx = dox.parseCodeContext('$User.prototype.$save = function(a,b){}');
ctx.type.should.equal('method');
ctx.constructor.should.equal('$User');
ctx.params.should.eql(['a','b']);
ctx.name.should.equal('$save');
},

Expand Down Expand Up @@ -585,10 +608,11 @@ module.exports = {
},

'test .parseCodeContext() method': function(){
var ctx = dox.parseCodeContext('$user.$save = function(){}');
var ctx = dox.parseCodeContext('$user.$save = function(a,b){}');
ctx.type.should.equal('method');
ctx.receiver.should.equal('$user');
ctx.name.should.equal('$save');
ctx.params.should.eql(['a','b']);
},

'test .parseCodeContext() property': function(){
Expand Down