2016-01-13 125 views
0

在發佈Mars之前,可以在Eclipse中安裝PHPMD支持,儘管some caveats and difficulties也支持。在Eclipse中集成PHPMD(PHP Mess Detector)Mars

現在來自PTI的支持似乎已被徹底刪除,即使development of PHPMD hasn't stopped和PHPMD確實提供了其他工具不具備的某些功能:例如,detect unused variables

對於這最後一個功能我找到了一個not too recent CodeSniffer plugin這個技巧。也有some sniffs應該做這項工作,但他們似乎並沒有爲我工作,或至少不是在所有情況下工作:我有一個需要重構的項目,我有11個來自CodeSniffer的警告和2524個來自PHPMD的警告。

我想我已經回到了shoehorning PHPMD的簡單和不雅的方式,但這樣做之前,我想知道是否有人有這個特定的同樣的問題/需要,以及是否他/她設法以某種方式解決這個問題。

回答

1

好的,所以在這裏。

我確實有一個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(和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的內容。