0

Mars がリリースされる前は、PHPMD サポートを Eclipse にインストールすることができましたが、いくつかの注意事項や問題がありました。

PHPMD の開発が停止しておらず、PHPMD が他のツールにはないいくつかの機能を提供しているとしても、PTI からのサポートは完全に削除されたようです。たとえば、未使用の変数を検出します。

この最後の機能については、このトリックを実行するあまり最近ではない CodeSniffer プラグインを見つけました。作業を行う必要があるいくつかのスニフもありますが、それらは私にとっては機能しないようです。または、少なくともすべての場合では機能しないようです。リファクタリングが必要なプロジェクトがあり、CodeSniffer から 11 個の警告があり、2524 個から 2524 個の警告がありますPHPMD.

私はPHPMDを元に戻す単純で洗練されていない方法を持っていると思いますが、それを行う前に、誰かがこの特定の同じ問題/ニーズを抱えているかどうか、そして彼/彼が何とかそれを解決できたかどうか疑問に思いました.

4

1 に答える 1

2

よし、これで行こう。

コマンドラインから動作する PHPMD バイナリがあります。私が計画したことは、その出力を CodeSniffer プラグインの出力に挿入し、後者を PHPMD メッセージで「充実」させることです。

この趣旨で、私phpcs.phpは自分のplugins/org.ppsrc.eclipse.pti.tools.codesniffer_.../php/toolsディレクトリに入っているものをめちゃくちゃにしました。

(私が CodeSniffer で抱えているもう 1 つの問題は、認識すべきファイルを頻繁に再スキャンすることであるため、CodeSniffer にメモリを与えることにしました。

まず、分析対象のファイルである呼び出しの最後の引数を抽出します (+++ でマークされた行は、私の追加/変更です)。

// Optionally use PHP_Timer to print time/memory stats for the run.
// Note that the reports are the ones who actually print the data
// as they decide if it is ok to print this data to screen.
@include_once 'PHP/Timer.php';
if (class_exists('PHP_Timer', false) === true) {
    PHP_Timer::start();
}

if (is_file(dirname(__FILE__).'/../CodeSniffer/CLI.php') === true) {
    include_once dirname(__FILE__).'/../CodeSniffer/CLI.php';
} else {
    include_once 'PHP/CodeSniffer/CLI.php';
}

+++ $lastArgument   = array_pop($_SERVER['argv']);

次に、いくつかのディレクトリを無視するなど、CS が渡していないようで必要なフラグをいくつか追加します。

+++ $_SERVER['argv'][]  = '--ignore=tests,vendor,cache';
+++ $_SERVER['argv'][]  = $lastArgument;

その後、CS 呼び出しが続行されますが、結果を直接 Eclipse に送信する代わりに、バッファーに保存します。

$phpcs = new PHP_CodeSniffer_CLI();
$phpcs->checkRequirements();
+++ ob_start();
$numErrors = $phpcs->process();

+++ $dom    = new DOMDocument();
+++ $dom->loadXML(ob_get_clean());

+++ $cs     = $dom->getElementsByTagName('phpcs')->item(0);
+++ $xpath  = new DOMXPath($dom);

これで、PHPCS 出力を XML として準備できました。

あとは、独自の構文を使用して PHPMD を呼び出すだけです。

// Add PHPMD.
$mdCmd  = "C:/PHP/composer/vendor/phpmd/phpmd/src/bin/phpmd \"{$lastArgument}\" xml \"C:/Program Files/eclipse/plugins/org.phpsrc.eclipse.pti.library.pear_1.2.2.R20120127000000/php/library/PEAR/data/PHP_PMD/resources/rulesets/codesize.xml,C:/Program Files/eclipse/plugins/org.phpsrc.eclipse.pti.library.pear_1.2.2.R20120127000000/php/library/PEAR/data/PHP_PMD/resources/rulesets/naming.xml,C:/Program Files/eclipse/plugins/org.phpsrc.eclipse.pti.library.pear_1.2.2.R20120127000000/php/library/PEAR/data/PHP_PMD/resources/rulesets/unusedcode.xml\"";

...そして別の XML にロードします。

    fprintf(STDERR, $mdCmd . "\n");
    $dompmd = new DOMDocument();
    $dompmd->loadXML($mdxml = shell_exec($mdCmd));

ここで、PMD オブジェクトからすべてのエラーを取得し、CS オブジェクトに追加します。

    $files  = $dompmd->getElementsByTagName('file');
    foreach ($files as $file) {
        $name   = $file->getAttribute('name');
        $list   = $xpath->query("//file[@name=\"{$name}\"]");
        if (null === $list) {
            continue;
        }
        $csFile = $list->item(0);
        if (null === $csFile) {
            // No errors from CS.
            $csFile = $dom->createElement('file');
            $csFile->setAttribute('name', $name);
            $csFile->setAttribute('errors', 0);
            $csFile->setAttribute('warnings', 0);
            $csFile->setAttribute('fixable', 0);
            $cs->appendChild($csFile);
        }
        $errs   = 0;
        foreach ($file->childNodes as $violation) {
            if ($violation instanceof \DOMText) {
                continue;
            }
            $error  = $dom->createElement('warning', trim($violation->nodeValue));


            $error->setAttribute('line', $violation->getAttribute('beginline'));
            $error->setAttribute('column', 1);
            $error->setAttribute('source', 'PHPMD.' . $violation->getAttribute('ruleset'));
            $error->setAttribute('severity', $violation->getAttribute('priority'));
            $error->setAttribute('fixable', 0);

            $csFile->appendChild($error);

            $errs++;
        }
        $csFile->getAttributeNode('errors')->value += $errs;
    }

最後に、データを Eclipse に送り返します。

print $dom->saveXML();
exit($numErrors ? 1: 0);

CodeSniffer のキャッシング (および PHPMD も)

私が CodeSniffer で抱えているもう 1 つの問題は、認識すべきファイルを頻繁に再スキャンすることであるため、CodeSniffer にメモリを与えることにしました。とても簡単です: 保存された XML と、元のファイル名の MD5とその内容から作成された名前を含む一時ファイルを保存できます。

/tmp/68ce1959ef67bcc94e05084e2e20462a.76e55e72f32156a20a183de82fe0b3b6.xml

したがって、PHPCS が analyze を要求されると、次/path/to/file/so-and-so.phpのようになります。

  • ファイル名の MD5 を作成します。
  • その内容の MD5 を作成します。
  • /tmp/md5file.md5content.xml が存在しない場合:
    • /tmp/md5file.*.xml を削除します。これらは廃止されています。
    • 上記のようにコードを実行します。
    • 結果を /tmp/md5file.md5content.xml に保存します
  • /tmp/md5file.md5content.xml の内容を出力します。
于 2016-02-07T19:06:33.527 に答える