使用JavaScript自定义规则进行静态分析?

使用JavaScript自定义规则进行静态分析?,javascript,code-analysis,jslint,jshint,Javascript,Code Analysis,Jslint,Jshint,JSLint、JSHint或其他开源静态代码分析工具是否支持添加代码遵从性的自定义规则,或者是否有一些符合ECMAScript的解析器可供我使用,以获得尽可能接近下面代码段中所示结果的结果 例如,我想查看JavaScript代码并列出调用的函数,如果它调用一个库(或智能手机为HTML5小部件提供的API)来注册该API的名称空间下的所有内容,创建一个对象及其属性树,查看函数是否从可追溯到的对象中调用,可能具有XML、JSON或其他结构化格式的输出 例如,假设我有这个JavaScript代码(它什

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

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

例如,假设我有这个JavaScript代码(它什么都不做,只是为了参数):

jobs=mylibrary.getJobs();
find=jobs.find(“Python”);
list=found.convert(“html”);
我希望我的analyzer工具得到以下信息:

{
“我的图书馆”:{
“作业”:{“制造者”:“获取作业”,“父项”:“mylibrary”},
“已找到”:{“maker”:“find”,“parent”:“jobs”,“parameters”:“Python”},
“列表”:{“制造者”:“转换”,“父项”:“找到”}
}
}

我尝试使用javascript解释器,可以从代码中访问它(在我的例子中是python)。所以像
pynoceros
pynarcissus
pyv8
这样的口译员可能会帮助我

关于如何安装py8,这里有一个答案:

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

就静态分析而言,我可以使用JSLINT解析器(): 但我不知道如何进一步使用它

{
    "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"
                    }
                ]
            }
        }
    ]
}

您应该能够使用substack构建类似的东西,substack使用来自的解析器,并提供您所需要的一切。快速示例:

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中的每个节点,其中每个
调用
节点将根据其值(函数名、对象名等)进行验证,如果不进行验证,将发出警告

这是上面的
burrito
调用的输出(注意:每个
[Object]
或类似的都被node.js'
控制台.log
截断。值实际上是burrito解析树中的节点,因此每个值都有其关联状态等)

更新:


另一个选择是较新的(?)ES解析器,它似乎开发得更积极,文档也更完善。据报道,它也比丑八怪快。您可以在上尝试解析。我认为,您应该能够使用此工具构建一个好的解决方案。

PMD支持使用自定义规则的ECMAScript静态分析:

以一个当前规则集为例。将其复制并粘贴到新文件中,删除其中的所有旧规则,并更改名称和说明

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

您还可以使用排除模式(可选的覆盖包含模式)将某些文件从规则集的处理中排除。当存在匹配的排除模式,但没有匹配的包含模式时,将从处理中排除文件

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

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

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

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

参考资料


您的意思是喜欢分析,但在HTML5内容上返回分析的XML数据吗?例如,监视所有点击HTML5音频的人,然后以XML数据的形式发送这些数据,以便您可以导出到图表等?@TheBlackBenzKid:我指的是静态分析(不是动态分析),而是代码(包括.js和部分),例如所有调用函数及其所属库的列表,匿名函数,“扩展”对象等。你不能尝试FireBug来查看DOM视图吗?@TheBlackBenzKid:那仍然是动态分析,事实上我需要的是生成类似DOM的结构(可能是XML或Jason),但只从javascript对象生成,而不通过浏览器引擎运行.js。谢谢你的回复,这让我想得更清楚我需要什么。对不起,我帮不了你更多的忙。谢谢你,这看起来是迄今为止最有希望的。我将继续使用它,看看我能完成什么。听起来不错——请看我关于Esprima的便条——它看起来确实很方便!埃斯普里马甚至更好,你的答案是迄今为止最好的,因为今天我完成了投票,而且我想把这个问题留到悬赏结束为止;)
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' ]