Skip to content

Commit

Permalink
Refactored context matching into an extensible array.
Browse files Browse the repository at this point in the history
  • Loading branch information
Twipped committed Mar 28, 2015
1 parent 0718075 commit 6da4f29
Showing 1 changed file with 220 additions and 144 deletions.
364 changes: 220 additions & 144 deletions lib/dox.js
Expand Up @@ -481,154 +481,230 @@ exports.parseParamOptional = function(tag) {
exports.parseCodeContext = function(str, parentContext) {
parentContext = parentContext || {};

// class, possibly exported by name or as a default
if (/^\s*(export(\s+default)?\s+)?class\s+([\w$]+)(\s+extends\s+([\w$]+))?\s*{/.exec(str)) {
return {
type: 'class'
, constructor: RegExp.$3
, cons: RegExp.$3
, name: RegExp.$3
, extends: RegExp.$5
, string: 'new ' + RegExp.$3 + '()'
};
// class constructor
} else if (/^\s*constructor\s*\(/.exec(str)) {
return {
type: 'constructor'
, constructor: parentContext.name
, cons: parentContext.name
, name: 'constructor'
, string: (parentContext && parentContext.name && parentContext.name + '.prototype.' || '') + 'constructor()'
};
// class method
} else if (/^\s*([\w$]+)\s*\(/.exec(str)) {
return {
type: 'method'
, constructor: parentContext.name
, cons: parentContext.name
, name: RegExp.$1
, string: (parentContext && parentContext.name && parentContext.name + '.prototype.' || '') + RegExp.$1 + '()'
};
// named function statement, possibly exported by name or as a default
} else if (/^\s*(export(\s+default)?\s+)?function\s+([\w$]+)\s*\(/.exec(str)) {
return {
type: 'function'
, name: RegExp.$3
, string: RegExp.$3 + '()'
};
// anonymous function expression exported as a default
} else if (/^\s*export\s+default\s+function\s*\(/.exec(str)) {
return {
type: 'function'
, name: RegExp.$1 // undefined
, string: RegExp.$1 + '()'
};
// function expression
} else if (/^return\s+function(?:\s+([\w$]+))?\s*\(/.exec(str)) {
return {
type: 'function'
, name: RegExp.$1
, string: RegExp.$1 + '()'
};
// function expression
} else if (/^\s*(?:const|let|var)\s+([\w$]+)\s*=\s*function/.exec(str)) {
return {
type: 'function'
, name: RegExp.$1
, string: RegExp.$1 + '()'
};
// prototype method
} else if (/^\s*([\w$.]+)\s*\.\s*prototype\s*\.\s*([\w$]+)\s*=\s*function/.exec(str)) {
return {
var ctx;

// loop through all context matchers, returning the first successful match
return exports.contextPatternMatchers.some(function (matcher) {
return ctx = matcher(str, parentContext);
}) && ctx;
};

exports.contextPatternMatchers = [

function (str) {
// class, possibly exported by name or as a default
if (/^\s*(export(\s+default)?\s+)?class\s+([\w$]+)(\s+extends\s+([\w$]+))?\s*{/.exec(str)) {
return {
type: 'class'
, constructor: RegExp.$3
, cons: RegExp.$3
, name: RegExp.$3
, extends: RegExp.$5
, string: 'new ' + RegExp.$3 + '()'
};
}
},

function (str, parentContext) {
// class constructor
if (/^\s*constructor\s*\(/.exec(str)) {
return {
type: 'constructor'
, constructor: parentContext.name
, cons: parentContext.name
, name: 'constructor'
, string: (parentContext && parentContext.name && parentContext.name + '.prototype.' || '') + 'constructor()'
};
// class method
}
},

function (str, parentContext) {
if (/^\s*([\w$]+)\s*\(/.exec(str)) {
return {
type: 'method'
, constructor: RegExp.$1
, cons: RegExp.$1
, name: RegExp.$2
, string: RegExp.$1 + '.prototype.' + RegExp.$2 + '()'
};
// prototype property
} else if (/^\s*([\w$.]+)\s*\.\s*prototype\s*\.\s*([\w$]+)\s*=\s*([^\n;]+)/.exec(str)) {
return {
type: 'property'
, constructor: RegExp.$1
, cons: RegExp.$1
, name: RegExp.$2
, value: RegExp.$3.trim()
, string: RegExp.$1 + '.prototype.' + RegExp.$2
};
// prototype property without assignment
} else if (/^\s*([\w$]+)\s*\.\s*prototype\s*\.\s*([\w$]+)\s*/.exec(str)) {
return {
type: 'property'
, constructor: RegExp.$1
, cons: RegExp.$1
, name: RegExp.$2
, string: RegExp.$1 + '.prototype.' + RegExp.$2
};
// inline prototype
} else if (/^\s*([\w$.]+)\s*\.\s*prototype\s*=\s*{/.exec(str)) {
return {
type: 'prototype'
, constructor: RegExp.$1
, cons: RegExp.$1
, name: RegExp.$1
, string: RegExp.$1 + '.prototype'
};
// inline method
} else if (/^\s*([\w$.]+)\s*:\s*function/.exec(str)) {
return {
type: 'method'
, constructor: parentContext.name
, cons: parentContext.name
, name: RegExp.$1
, string: (parentContext && parentContext.name && parentContext.name + '.prototype.' || '') + RegExp.$1 + '()'
};
// inline property
} else if (/^\s*([\w$.]+)\s*:\s*([^\n;]+)/.exec(str)) {
return {
type: 'property'
, constructor: parentContext.name
, cons: parentContext.name
, name: RegExp.$1
, value: RegExp.$2.trim()
, string: (parentContext && parentContext.name && parentContext.name + '.' || '') + RegExp.$1
};
// inline getter/setter
} else if (/^\s*(get|set)\s*([\w$.]+)\s*\(/.exec(str)) {
return {
type: 'property'
, constructor: parentContext.name
, cons: parentContext.name
, name: RegExp.$2
, string: (parentContext && parentContext.name && parentContext.name + '.prototype.' || '') + RegExp.$2
};
// method
} else if (/^\s*([\w$.]+)\s*\.\s*([\w$]+)\s*=\s*function/.exec(str)) {
return {
, constructor: parentContext.name
, cons: parentContext.name
, name: RegExp.$1
, string: (parentContext && parentContext.name && parentContext.name + '.prototype.' || '') + RegExp.$1 + '()'
};
// 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)) {
return {
type: 'function'
, name: RegExp.$3
, string: RegExp.$3 + '()'
};
}
},

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

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

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

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

function (str) {
// prototype property
if (/^\s*([\w$.]+)\s*\.\s*prototype\s*\.\s*([\w$]+)\s*=\s*([^\n;]+)/.exec(str)) {
return {
type: 'property'
, constructor: RegExp.$1
, cons: RegExp.$1
, name: RegExp.$2
, value: RegExp.$3.trim()
, string: RegExp.$1 + '.prototype.' + RegExp.$2
};
}
},

function (str) {
// prototype property without assignment
if (/^\s*([\w$]+)\s*\.\s*prototype\s*\.\s*([\w$]+)\s*/.exec(str)) {
return {
type: 'property'
, constructor: RegExp.$1
, cons: RegExp.$1
, name: RegExp.$2
, string: RegExp.$1 + '.prototype.' + RegExp.$2
};
}
},

function (str) {
// inline prototype
if (/^\s*([\w$.]+)\s*\.\s*prototype\s*=\s*{/.exec(str)) {
return {
type: 'prototype'
, constructor: RegExp.$1
, cons: RegExp.$1
, name: RegExp.$1
, string: RegExp.$1 + '.prototype'
};
}
},

function (str, parentContext) {
// inline method
if (/^\s*([\w$.]+)\s*:\s*function/.exec(str)) {
return {
type: 'method'
, receiver: RegExp.$1
, name: RegExp.$2
, string: RegExp.$1 + '.' + RegExp.$2 + '()'
};
// property
} else if (/^\s*([\w$.]+)\s*\.\s*([\w$]+)\s*=\s*([^\n;]+)/.exec(str)) {
return {
, constructor: parentContext.name
, cons: parentContext.name
, name: RegExp.$1
, string: (parentContext && parentContext.name && parentContext.name + '.prototype.' || '') + RegExp.$1 + '()'
};
}
},

function (str, parentContext) {
// inline property
if (/^\s*([\w$.]+)\s*:\s*([^\n;]+)/.exec(str)) {
return {
type: 'property'
, constructor: parentContext.name
, cons: parentContext.name
, name: RegExp.$1
, value: RegExp.$2.trim()
, string: (parentContext && parentContext.name && parentContext.name + '.' || '') + RegExp.$1
};
}
},

function (str, parentContext) {
// inline getter/setter
if (/^\s*(get|set)\s*([\w$.]+)\s*\(/.exec(str)) {
return {
type: 'property'
, receiver: RegExp.$1
, name: RegExp.$2
, value: RegExp.$3.trim()
, string: RegExp.$1 + '.' + RegExp.$2
};
// declaration
} else if (/^\s*(?:const|let|var)\s+([\w$]+)\s*=\s*([^\n;]+)/.exec(str)) {
return {
type: 'declaration'
, name: RegExp.$1
, value: RegExp.$2.trim()
, string: RegExp.$1
};
, constructor: parentContext.name
, cons: parentContext.name
, name: RegExp.$2
, string: (parentContext && parentContext.name && parentContext.name + '.prototype.' || '') + RegExp.$2
};
}
},

function (str) {
// method
if (/^\s*([\w$.]+)\s*\.\s*([\w$]+)\s*=\s*function/.exec(str)) {
return {
type: 'method'
, receiver: RegExp.$1
, name: RegExp.$2
, string: RegExp.$1 + '.' + RegExp.$2 + '()'
};
}
},

function (str) {
// property
if (/^\s*([\w$.]+)\s*\.\s*([\w$]+)\s*=\s*([^\n;]+)/.exec(str)) {
return {
type: 'property'
, receiver: RegExp.$1
, name: RegExp.$2
, value: RegExp.$3.trim()
, string: RegExp.$1 + '.' + RegExp.$2
};
}
},

function (str) {
// declaration
if (/^\s*(?:const|let|var)\s+([\w$]+)\s*=\s*([^\n;]+)/.exec(str)) {
return {
type: 'declaration'
, name: RegExp.$1
, value: RegExp.$2.trim()
, string: RegExp.$1
};
}
}
};
];

exports.setMarkedOptions = function(opts) {
markdown.setOptions(opts);
Expand Down

0 comments on commit 6da4f29

Please sign in to comment.