0

在 Mars 发布之前,可以在 Eclipse 中安装 PHPMD 支持,尽管有一些警告和困难

现在 PTI 的支持似乎已被完全删除,即使PHPMD 的开发没有停止并且 PHPMD 确实提供了其他工具不提供的一些功能:例如,检测未使用的变量

对于这最后一个功能,我发现了一个不太新的 CodeSniffer 插件可以解决问题。还有一些嗅探器应该可以完成工作,但它们似乎对我不起作用,或者至少在所有情况下都不起作用:我有一个需要重构的项目,我有来自 CodeSniffer 的 11 个警告和来自 CodeSniffer 的 2524 个警告PHPMD。

我想我有一种简单而不优雅的方式来重新插入 PHPMD,但在这样做之前我想知道是否有人有这个特定的相同问题/需求,以及他/她是否设法以某种方式解决它。

4

1 回答 1

2

好的,就到这里吧。

我确实有一个可以从命令行运行的 PHPMD 二进制文件。我计划做的是将其输出注入 CodeSniffer 插件的输出,用 PHPMD 消息“丰富”后者。

为此,我修改phpcs.phpplugins/org.ppsrc.eclipse.pti.tools.codesniffer_.../php/tools目录中的内容。

(因为我对 CodeSniffer 的另一个问题是它经常会重新扫描它应该知道的文件,所以我决定给 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);

现在我已经准备好作为 XML 的 PHPCS 输出。

剩下的就是使用自己的语法调用 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 的另一个问题是它经常会重新扫描它应该知道的文件,所以我决定给 CodeSniffer 一个内存。这很简单:我可以使用保存的 XML 和由原始文件名及其内容的 MD5 构建的名称存储一个临时文件:

/tmp/68ce1959ef67bcc94e05084e2e20462a.76e55e72f32156a20a183de82fe0b3b6.xml

所以当 PHPCS 被要求分析/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 回答