[Apex PMD] VSCodeでApexの静的解析を行う

## Apex PMDとは
Apex PMDはApexのソースコードを静的解析し、問題のある箇所を検知するVSCodeの拡張機能です。
問題箇所の早期発見が容易になります。

![ApexPMD_Result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125621/c07f672f-316e-6862-5470-5c987feefe7a.png)

## Apex PMD 導入方法
マーケットプレイスから下記の拡張機能をインストールします。

https://marketplace.visualstudio.com/items?itemName=chuckjonas.apex-pmd

インストールしたら、静的解析を行いたいApexファイルを開き、コマンドパレットで`Apex Static Analysis: On File`を実行するだけで静的解析されます。
プロジェクト全体で静的解析したい場合は`Apex Static Analysis: On Workspace`を実行します。
表示されたエラーをクリアしたい場合は`Apex Static Analysis: Clear Problems`を実行します。

![ApexPMD_CommandParret.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125621/881da3f2-2b2e-e44a-4798-267a2f399b9c.png)

コマンドパレットからの実行の他、ファイルを保存したときにも実行されます。この設定は設定画面から変更ができます。
「Run On File Change」 をチェックすることでファイル変更時点で静的解析されます。

![ApexPMD_Setting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125621/18d5f865-f1b9-471b-1f05-79f1486ba21a.png)


## 独自のルールセットを作成する
静的解析の検知対象はルールセットで定義されています。
エラー、警告などプライオリティを変更したい場合、不要なルールを無効にしたい場合などは独自のルールセットを使用することができます。
ルールセットは公式ドキュメントのルールリファレンス[^doc-1]に従って、XMLファイルで記述します。
作成したルールセットは設定画面で追加できます。複数ファイル使用することもできます。

![ApexPMD_CustomRules2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125621/ef57588c-14b5-8795-648d-2bcd9700a8f6.png)

下記はルールセットの例になります。

```xml:best-practice.xml
<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="Best Practices"
    xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
    <description>一般的に受け入れられているベストプラクティスを実施するルール。</description>
    <exclude-pattern>.*/.sfdx/.*</exclude-pattern>

<!--
    priority 1: error
    priority 3: warn
    priority 5: hint
-->

    <!-- アサートメソッドはメッセージを設定してください。 -->
    <rule ref="category/apex/bestpractices.xml/ApexAssertionsShouldIncludeMessage">
        <priority>5</priority>
    </rule>

    <!-- テストメソッドには少なくとも1つのアサーションを含める必要があります。 -->
    <rule
        ref="category/apex/bestpractices.xml/ApexUnitTestClassShouldHaveAsserts"
        message="Apex unit test classes should have at least one System.assert() or assertEquals() or AssertNotEquals() call">
        <priority>3</priority>
    </rule>

    <!-- testMethodキーワードは非推奨です。@IsTestアノテーションを使用してください。 -->
    <rule ref="category/apex/bestpractices.xml/ApexUnitTestMethodShouldHaveIsTestAnnotation" >
        <priority>1</priority>
    </rule>

    <!-- @IsTest(seeAllData=true)は使用できません。 -->
    <rule
        ref="category/apex/bestpractices.xml/ApexUnitTestShouldNotUseSeeAllDataTrue"
        message="@isTest(seeAllData=true) should not be used in Apex unit tests because it opens up the existing database data for unexpected modification by tests">
        <priority>1</priority>
    </rule>

    <!-- RestResource、WebService以外のメソッドはglobalにできません。 -->
    <rule
        ref="category/apex/bestpractices.xml/AvoidGlobalModifier"
        message="Avoid using global modifier">
        <priority>1</priority>
    </rule>

    <!-- トリガにロジックは記述せず、トリガハンドラを使用してください。 -->
    <rule
        ref="category/apex/bestpractices.xml/AvoidLogicInTrigger"
        message="Avoid logic in triggers">
        <priority>3</priority>
    </rule>

    <!-- デバッグにログレベルを設定してください。 -->
    <rule ref="category/apex/bestpractices.xml/DebugsShouldUseLoggingLevel">
        <priority>3</priority>
        <properties>
            <!-- LoggingLevel.DEBUGを検出する場合はtrue -->
            <property name="strictMode" value="false" />
        </properties>
    </rule>

    <!-- 使用されていない変数は宣言しないでください。 -->
    <rule ref="category/apex/bestpractices.xml/UnusedLocalVariable">
        <priority>1</priority>
    </rule>
</ruleset>
```

## ルールを自作する
カスタムルールを自作してルールセットに追加することも可能のようです。
https://pmd.github.io/latest/pmd_userdocs_extending_writing_pmd_rules.html

## 参考
- [Apex PMD - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=chuckjonas.apex-pmd)
- [Apex Rules | PMD Source Code Analyzer](https://pmd.github.io/latest/pmd_rules_apex.html)
- [vscode-apex-pmd/apex_ruleset.xml at master · ChuckJonas/vscode-apex-pmd](https://github.com/ChuckJonas/vscode-apex-pmd/blob/master/rulesets/apex_ruleset.xml)

<!-- 脚注 -->
[^doc-1]: https://pmd.github.io/latest/pmd_rules_apex.html