LoginSignup
3
4

More than 5 years have passed since last update.

phpmdでコード解析+チェックルールのカスタマイズしてみる

Posted at

phpcsに続きコーディングの品質向上のためphpmdを使うようにしてみました。

phpmd

phpmdは潜在的にバグになりそうなコードや改善の余地があるコードなどを検出してくれるツールです

phpmdインストール

公式通り、composer.jsonに下記を追記してcomposer installします

{
    "require-dev": {
        "phpmd/phpmd" : "*"
    }
}

使い方

コマンドラインで実行する際は下記のように実行できます。
phpmd /path/to/file xml codesize,naming,cleancode

xml以後のオプションで検出ルールを指定します。
ルールが設定してあるxmlはvendor/phpmd/phpmd/src/main/resources/rulesets/以下にあります。

デフォルトでは下記があります。

  • cleancode.xml
  • codesize.xml
  • controversial.xml
  • design.xml
  • naming.xml
  • unusedcode.xml

またそれぞれのルールの実装はvendor/phpmd/phpmd/src/main/php/PHPMD/Rule/にあります。

なので、ルールのカスタマイズするには、新規にruleを定義したxmlを作成して、それに対するチェックの実装を行っていく感じになります。

カスタマイズルールを作ってみる

今回はtypoチェックを実装してみました。

まずカスタマイズルール用にxmlを作ります。

vi vendor/phpmd/phpmd/src/main/resources/rulesets/myStandard.xml


<?xml version="1.0"?>

<ruleset name="My Standard Rules">

    <description>
This ruleset contains a my standard rules.
    </description>

    <rule name="CheckTypo"
          since="0.2"
          message = "Maybe typo. {0} : {1} -> {2}"
          class="PHPMD\Rule\MyStandard\CheckTypo"
          externalInfoUrl="#">
        <description>
            <![CDATA[
Maybe typo.
            ]]>
        </description>
        <priority>1</priority>
        <properties />
        <example>
            <![CDATA[
protocal->protocol
recompence->recompense
            ]]>
        </example>
    </rule>
</ruleset>

上記のように定義して、PHPMD\Rule\MyStandard\CheckTypoにチェックルールの実装を行っていきます。

typo例はこちらのものを参考としました。

Lists_of_common_misspellings

既存の実装を元に下記のように実装してみました。
./resources/typoList.csvにtypo単語リストを置いています

vendor/phpmd/phpmd/src/main/php/PHPMD/Rule/MyStandard/CheckTypo.php


namespace PHPMD\Rule\MyStandard;

use PHPMD\AbstractNode;
use PHPMD\AbstractRule;
use PHPMD\Rule\FunctionAware;
use PHPMD\Rule\MethodAware;

/**
 * This rule CheckTypo.
 * typo check
 *
 */
class CheckTypo extends AbstractRule implements MethodAware, FunctionAware
{

    private static $typoList = [];

    /**
     * This method checks typo
     *
     * @param \PHPMD\AbstractNode $node
     * @return void
     */
    public function apply(AbstractNode $node)
    {
        $typoList = $this->getTypoList();

        foreach ($node->findChildrenOfType('Variable') as $variable) {
            $image = $variable->getImage();
            foreach ($typoList as $key => $value) {
                if (preg_match("/$key/", $image)) {
                    $this->addViolation($variable, array($image, $key, $value));
                    break;
                }
            }
        }
    }

    /**
     * get typoList
     * @return void
     */
    public function getTypoList()
    {
        if (self::$typoList) {
            return self::$typoList;
        }
        $typoList = [];
        $fp = fopen(dirname(__FILE__) . "/resources/typoList.csv", "r");
        while (!feof($fp)) {
                $tmpArr = fgetcsv($fp);
                $typoList[$tmpArr[0]] = $tmpArr[1];
        }
        self::$typoList = $typoList;
        fclose($fp);

        return self::$typoList;
    }
}

実行はこんな感じで、
phpmd /path/to/file xml myStandard

既存の実装を元になんとなくやってみましたが、変数名のtypo検出ができました!

こんな感じでカスタマイズルールを実装することでプロジェクト共通で品質向上やレビューの負荷軽減等していけたらと思いますん。

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4