[英]Esprima get function and variable declarations
I want to get all function and variable declarations made in a Javascript code.我想获得在 Javascript 代码中进行的所有函数和变量声明。 I use esprima and I wonder if there is script that I can use for my goal?
我使用 esprima,我想知道是否有可以用于我的目标的脚本?
For example we have this code:例如我们有这样的代码:
var myVar1;
var myVar2;
function myTestFunction(funcVar1, funcVar2) {
var myVar3;
}
What I except:我除了:
Array with variables带变量的数组
["myVar1", "myVar2"]
And an array with functions:还有一个带有函数的数组:
[{"name": "myTestFuncttion", "params":["funcVar1", "funcVar2"], "variables": ["myVar3"]}]
Any ideas how to achieve this?任何想法如何实现这一目标?
Complete solution with fiddle:使用小提琴的完整解决方案:
Here is some JavaScript code for a test-run:下面是一些用于测试运行的 JavaScript 代码:
var hello = 41;
function aaaaa(p1, p2, p3){
var a1 = 7, a2 = 8;
var a3 = 9;
function bbbbb(q1, q2){
var b1 = 10, b2 = 11;
return 12;
}
var a4 = 99;
function ccccc(r1, r2, r3){
var c1 = 13;
var c2 = 14;
var c3 = 15, c4 = 16;
return 17;
}
var a5 = 88, a6 = 77;
function ddddd(s1){
return s1 === 18
? function (x){ return x+1; }
: function (y){ return 22; }
}
return p1 + a3 <= 42 ? 55 : ccc(p1, 0, 0);
}
var world = 42;
function xxxxx(x){
var z=0;
return 0;
}
I'm assuming that this is the desired output:我假设这是所需的输出:
{
"vars": ["hello", "world" ],
"funcs": [
{
"name": "aaaaa",
"params": ["p1", "p2", "p3"],
"variables": ["a1","a2","a3","a4","a5","a6"]
},
{
"name": "bbbbb",
"params": ["q1","q2"],
"variables": ["b1","b2"]
},
{
"name": "ccccc",
"params": ["r1","r2","r3"],
"variables": ["c1","c2","c3","c4"]
},
{
"name": "ddddd",
"params": ["s1"],
"variables": []
},
{
"name": "xxxxx",
"params": ["x"],
"variables": ["z"]
}
]
}
The lists are flat and the anonymous functions within ddddd are being ignored (they are FunctionExpressions not FunctionDeclarations).列表是扁平的,ddddd 中的匿名函数被忽略(它们是 FunctionExpressions 而不是 FunctionDeclarations)。 Guessing that this is how you want it.
猜测这就是你想要的。
Here is the code - probably / hopefully easy to understand without further explanation:这是代码 - 可能/希望很容易理解,无需进一步解释:
function findDeclarations(code){
var ast = esprima.parse(code);
var funcDecls = [];
var globalVarDecls = [];
var funcStack = [];
function visitEachAstNode(root, enter, leave){
function visit(node){
function isSubNode(key){
var child = node[key];
if (child===null) return false;
var ty = typeof child;
if (ty!=='object') return false;
if (child.constructor===Array) return ( key!=='range' );
if (key==='loc') return false;
if ('type' in child){
if (child.type in esprima.Syntax) return true;
debugger; throw new Error('unexpected');
} else { return false; }
}
enter(node);
var keys = Object.keys(node);
var subNodeKeys = keys.filter(isSubNode);
for (var i=0; i<subNodeKeys.length; i++){
var key = subNodeKeys[i];
visit(node[key]);
}
leave(node);
}
visit(root);
}
function myEnter(node){
if (node.type==='FunctionDeclaration') {
var current = {
name : node.id.name,
params : node.params.map(function(p){return p.name;}),
variables : []
}
funcDecls.push(current);
funcStack.push(current);
}
if (node.type==='VariableDeclaration'){
var foundVarNames = node.declarations.map(function(d){ return d.id.name; });
if (funcStack.length===0){
globalVarDecls = globalVarDecls.concat(foundVarNames);
} else {
var onTopOfStack = funcStack[funcStack.length-1];
onTopOfStack.variables = onTopOfStack.variables.concat(foundVarNames);
}
}
}
function myLeave(node){
if (node.type==='FunctionDeclaration') {
funcStack.pop();
}
}
visitEachAstNode(ast, myEnter, myLeave);
return {
vars : globalVarDecls,
funcs : funcDecls
};
}
for testing, you can type为了测试,你可以输入
JSON.stringify(
findDeclarations(
'var hello=41;\n' +
aaaaa.toString() +
'var world=42;\n' +
xxxxx.toString()
),
null, 4
)
You can also use the estraverse package, it's available on github.你也可以使用 estraverse 包,它在 github 上可用。 Then, essentially, the function visitEachAstNode should be replaced by estraverse.traverse, and otherwise you can leave the code unchanged.
然后,本质上,函数visitEachAstNode 应该替换为estraverse.traverse,否则您可以保持代码不变。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.