From 6da4f29495113127bae01382cf3e758f9f356327 Mon Sep 17 00:00:00 2001 From: ChiperSoft Date: Sat, 28 Mar 2015 14:27:17 -0700 Subject: [PATCH] Refactored context matching into an extensible array. --- lib/dox.js | 364 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 220 insertions(+), 144 deletions(-) diff --git a/lib/dox.js b/lib/dox.js index ae0a1c51..321c9278 100644 --- a/lib/dox.js +++ b/lib/dox.js @@ -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);