4

JSLint、JSHint 或其他一些开源静态代码分析工具是否支持为代码合规性添加自定义规则,或者是否有一些符合 ECMAScript 的解析器,我可以使用这些解析器来获得尽可能接近下面代码片段中的结果?

例如,我想查看 JavaScript 代码并列出调用了哪些函数,如果它调用一个库(或智能手机为 HTML5 小部件提供的 API)来注册该 API 命名空间下的所有内容,以制作一棵树对象及其属性,以查看是否从可以追溯的对象中调用函数,可能使用 XML、JSON 或其他结构化格式的输出。

比如说我有这个 JavaScript 代码(它什么都不做,只是为了论证):

jobs = mylibrary.getJobs();
found = jobs.find("Python");
list = found.convert("html");

我希望我的分析工具得到这个:

{
    "mylibrary": {
        "jobs": {"maker":"getJobs", "parent": "mylibrary"},
        "found": {"maker": "find", "parent": "jobs", "parameters": "Python"},
        "list": {"maker": "convert", "parent": "found"}
    }
}
4

3 回答 3

3

你应该能够使用 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 解析不是很精通),但我相信这需要您付出一些努力。也许你不需要中间的结构,可以这么说,但可以只验证墨西哥卷饼中的每个节点,每个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 更快。您可以在Parsing Demo 页面上尝试例如解析。我认为,您应该能够使用它构建一个好的解决方案。

于 2012-09-10T13:29:04.447 回答
1

我尝试了一个可以从代码访问的javascript解释器(在我的例子中是python)。所以口译员喜欢pynocerospynarcissus或者pyv8可能会帮助我。

这里有一个关于如何安装 py8 的答案:https ://stackoverflow.com/a/11879224/1577343

由于使用上述方法并没有取得多大成功,我更喜欢使用符合 ECMAScript 的解析器的静态分析解决方案。

到目前为止,我可以通过静态分析使用 JSLINT 解析器(在 .js 文件上运行 JSLint,从 chrome 或 firefox 的调试控制台):但我不知道如何进一步使用它。

{
    "string": "(begin)",
    "first": [
        {
            "string": "var",
            "arity": "statement",
            "first": [
                {
                    "string": "jobs"
                },
                {
                    "string": "found"
                },
                {
                    "string": "list"
                }
            ]
        },
        {
            "string": "=",
            "arity": "infix",
            "first": {
                "string": "jobs"
            },
            "second": {
                "string": "(",
                "arity": "infix",
                "first": {
                    "string": ".",
                    "arity": "infix",
                    "first": {
                        "string": "mylibrary"
                    },
                    "second": {
                        "string": "getJobs"
                    }
                },
                "second": []
            }
        },
        {
            "string": "=",
            "arity": "infix",
            "first": {
                "string": "found"
            },
            "second": {
                "string": "(",
                "arity": "infix",
                "first": {
                    "string": ".",
                    "arity": "infix",
                    "first": {
                        "string": "jobs"
                    },
                    "second": {
                        "string": "find"
                    }
                },
                "second": [
                    {
                        "string": "Python",
                        "arity": "string"
                    }
                ]
            }
        },
        {
            "string": "=",
            "arity": "infix",
            "first": {
                "string": "list"
            },
            "second": {
                "string": "(",
                "arity": "infix",
                "first": {
                    "string": ".",
                    "arity": "infix",
                    "first": {
                        "string": "found"
                    },
                    "second": {
                        "string": "convert"
                    }
                },
                "second": [
                    {
                        "string": "html",
                        "arity": "string"
                    }
                ]
            }
        }
    ]
}
于 2012-08-07T12:43:55.793 回答
1

PMD 支持带有自定义规则的 ECMAScript 静态分析:

以当前规则集之一为例。将其复制并粘贴到新文件中,从中删除所有旧规则,然后更改名称和描述。

请注意,您可以自定义单个引用的规则。在您的自定义规则集中,除了规则的类之外的所有内容都可以被覆盖。

您还可以使用排除模式将某些文件排除在规则集的处理范围之外,并使用可选的覆盖包含模式。当存在匹配的排除模式但没有匹配的包含模式时,文件将被排除在处理之外。

源文件路径中的路径分隔符被规范化为“/”字符,因此可以在多个平台上透明地使用相同的规则集。

此外,无论如何使用 PMD(例如命令行、IDE、Ant),这种排除/包含技术都可以工作,从而更容易在整个环境中保持 PMD 规则的应用一致。

您可以在内置 PMD 规则集旁边指定自定义规则集名称的完整路径

要在 IDE 中查看它,请将其添加到 rulesets/rulesets.properties

参考

于 2017-07-14T16:06:08.197 回答