Перед выпуском Mars было возможно установить поддержку PHPMD в Eclipse, хотя и с некоторые предостережения и трудности.
Теперь поддержка со стороны PTI, похоже, полностью удалена, даже если разработка PHPMD не остановилась и PHPMD предлагает некоторые функции, которых нет у других инструментов: например, обнаружить неиспользуемые переменные.
Для этой последней функции я нашел не слишком свежий плагин CodeSniffer это делает трюк. Это также некоторые нюхают это должно сработать, но они, похоже, не работают для меня, или, по крайней мере, не во всех случаях: у меня есть проект, требующий рефакторинга, для которого у меня есть 11 предупреждений из CodeSniffer и 2524 из PHPMD.
Я думаю, что у меня есть простой и не элегантный способ вставить PHPMD обратно, но прежде чем делать тот, Я задавался вопросом, есть ли у кого-то эта та же самая проблема / потребность, и удалось ли ему как-то решить ее.
Хорошо, вот так.
У меня есть двоичный файл PHPMD, который работает из командной строки. Что я планировал сделать, так это вставить свой вывод в плагин CodeSniffer, «обогатить» последнее сообщениями PHPMD.
Для этого я покалечил phpcs.php
который входит в мой plugins/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);
Теперь у меня есть готовый вывод 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, это то, что он часто повторно сканирует файлы. должен Чтобы узнать о, я решил дать CodeSniffer память. Это довольно просто: я могу сохранить временный файл с сохраненным XML и именем, созданным из MD5 исходного имени файла а также его содержание:
/tmp/68ce1959ef67bcc94e05084e2e20462a.76e55e72f32156a20a183de82fe0b3b6.xml
Поэтому, когда PHPCS попросили проанализировать /path/to/file/so-and-so.php
, будет:
Других решений пока нет …