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

サブスタックの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ます。値は実際にはブリトーの解析ツリー内のノードであるため、各値には関連付けられた状態などがあります)。

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' ]

アップデート:

もう 1 つのオプションは、より新しい (?) ES パーサーEsprimaです。これは、より積極的に開発され、より適切に文書化されているようです。また、伝えられるところによると、Ugliify よりも高速です。Parsing Demo pageで解析などを試すことができます。これを使用して、良いソリューションを構築できるはずです。

于 2012-09-10T13:29:04.447 に答える
1

コードからアクセスできるJavaScriptインタープリターで何かを試しました(私の場合はpython)。だから、通訳者はpynocerospynarcissusまたはpyv8私を助けるかもしれません.

py8 のインストール方法に関する回答がここにあります: https://stackoverflow.com/a/11879224/1577343

上記のアプローチではあまり成功しなかったので、ECMAScript 準拠のパーサーを使用する静的分析ソリューションを好みます。

私が得ることができる限りの静的分析では、JSLINTパーサーを使用しています(chromeまたはfirefoxのデバッグコンソールから.jsファイルで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"
                    }
                ]
            }
        }
    ]
}
于 2012-08-07T12:43:55.793 に答える