您应该能够使用substack的burrito构建类似这样的东西,它使用Uglify-JS中的解析器,我认为它可以提供您所需的一切。以下是一个快速示例:
src.js:
var jobs, found, list;
jobs = mylibrary.getJobs();
found = jobs.find("Python");
list = found.convert("html");
ast.js:
var fs = require('fs'),
burrito = require('burrito');
var src = fs.readFileSync('./src.js', 'utf8');
burrito(src, function (node) {
console.log(node.name, node.value);
});
关于如何构建您请求的结构,我不太确定(我自己对AST解析并不很熟悉),但我相信这需要一些努力。也许你不需要一个“中间”的结构,而是可以验证从 burrito 中每个节点,其中每个 call
节点将根据其值进行验证(函数名、对象名等),如果无法验证,则会提出警告。
下面是上述 burrito
调用的输出(注意:每个 [Object]
或类似的东西都已被 node.js 的 console.log
截断。实际上,这里的值是 burrito 解析树中的节点,因此每个值都有其关联的状态等)。
var [ [ [ 'jobs' ], [ 'found' ], [ 'list' ] ] ]
stat [ [ { name: 'assign', start: [Object], end: [Object] },
true,
[ [Object], 'jobs' ],
[ [Object], [Object], [] ] ] ]
assign [ true,
[ { name: 'name', start: [Object], end: [Object] }, 'jobs' ],
[ { name: 'call', start: [Object], end: [Object] },
[ 'dot', [Object], 'getJobs' ],
[] ] ]
name [ 'jobs' ]
call [ [ 'dot', [ 'name', 'mylibrary' ], 'getJobs' ], [] ]
stat [ [ { name: 'assign', start: [Object], end: [Object] },
true,
[ [Object], 'found' ],
[ [Object], [Object], [Object] ] ] ]
assign [ true,
[ { name: 'name', start: [Object], end: [Object] }, 'found' ],
[ { name: 'call', start: [Object], end: [Object] },
[ 'dot', [Object], 'find' ],
[ [Object] ] ] ]
name [ 'found' ]
call [ [ 'dot', [ 'name', 'jobs' ], 'find' ],
[ [ [Object], 'Python' ] ] ]
string [ 'Python' ]
stat [ [ { name: 'assign', start: [Object], end: [Object] },
true,
[ [Object], 'list' ],
[ [Object], [Object], [Object] ] ] ]
assign [ true,
[ { name: 'name', start: [Object], end: [Object] }, 'list' ],
[ { name: 'call', start: [Object], end: [Object] },
[ 'dot', [Object], 'convert' ],
[ [Object] ] ] ]
name [ 'list' ]
call [ [ 'dot', [ 'name', 'found' ], 'convert' ],
[ [ [Object], 'html' ] ] ]
string [ 'html' ]
更新:
另一个选择是较新的ES解析器Esprima,它似乎被更积极地开发和更好地记录。据报道,它比Uglify更快。您可以在解析演示页面上尝试解析等操作。使用这个工具,您应该能够构建一个很好的解决方案。