かんがるーさんの日記

最近自分が興味をもったものを調べた時の手順等を書いています。今は Spring Boot をいじっています。

Spring Boot 1.4.x の Web アプリを 1.5.x へバージョンアップする ( その11 )( build.gradle への PMD の導入 )

概要

記事一覧こちらです。

Spring Boot 1.4.x の Web アプリを 1.5.x へバージョンアップする ( その10 )( 起動時の spring.profiles.active のチェック処理を Set.contains を使用した方法に変更する ) の続きです。

参照したサイト・書籍

  1. PMD
    https://pmd.github.io/

  2. Gradle で PMD による静的解析を実行する
    http://maku77.github.io/gradle/pmd/pmd.html

  3. mychaelstyle/build.gradle - Example Gradle build Java with FindBugs and PMD and CPD
    https://gist.github.com/mychaelstyle/9826322

  4. How to find PMD Rulesets names in Gradle >2.0
    https://stackoverflow.com/questions/25584501/how-to-find-pmd-rulesets-names-in-gradle-2-0

  5. pmd/pmd - pmd/pmd-java/src/main/resources/rulesets/java/
    https://github.com/pmd/pmd/tree/master/pmd-java/src/main/resources/rulesets/java

    • build.gradle の ruleSets に記述する名称はどこを見ればよいのかがよく分からなかったのですが、どうもこのディレクトリを見ればよいらしいです。末尾の “.xml” を取り除いて、先頭に “java-” を付ければ ruleSet 名になります。
  6. How can getters/setters be ignored in the PMD CommentRequired rule?
    https://stackoverflow.com/questions/30869538/how-can-getters-setters-be-ignored-in-the-pmd-commentrequired-rule

  7. How to make a new rule set
    https://pmd.github.io/pmd-5.7.0/customizing/howtomakearuleset.html#

  8. @SuppressWarnings more than one rule not working
    https://stackoverflow.com/questions/22855796/suppresswarnings-more-than-one-rule-not-working

目次

  1. build.gradle を変更する
  2. build タスクを実行する
  3. RuleSets を1つずつ適用して出力されるメッセージを確認し、適用するか否か判断する
    1. java-basic
    2. java-braces
    3. java-clone
    4. java-codesize
    5. java-comments
    6. java-controversial
    7. java-coupling
    8. java-design
    9. java-empty
    10. java-finalizers
    11. java-imports
    12. java-logging-jakarta-commons
    13. java-logging-java
    14. java-naming
    15. java-optimizations
    16. java-strictexception
    17. java-strings
    18. java-sunsecure
    19. java-typeresolution
    20. java-unnecessary
    21. java-unusedcode
    22. pmd-project-rulesets.xml を作成し、build.gradle を変更する
  4. 再び build タスクを実行する
  5. 続きます。。。

手順

build.gradle を変更する

  1. build.gradle を リンク先のその1の内容 に変更します。

  2. 変更後、Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。

build タスクを実行する

  1. clean タスク → Rebuild Project → build タスク の順に実行します。

    build タスクが実行されるといろいろダウンロードされます。また Removed misconfigured rule: LoosePackageCoupling cause: No packages or classes specified というメッセージも出力されていました。

    f:id:ksby:20170624153320p:plain

    その後 PMD のチェック処理が実行されて 1761 PMD rule violations were found. というメッセージが出力されました。checkstyle, findbugs で警告・エラーが出なくなっているので大丈夫なのでは?と思っていましたが、かなり大量にメッセージが出ますね。。。

    f:id:ksby:20170624154136p:plain

    そんなに大量に指摘されても全て対応することはできないので、RuleSet を1つずつ確認して、どのようなメッセージが出るのか、またその RuleSet を適用すべきか、を判断します。

RuleSet を1つずつ適用して出力されるメッセージを確認し、適用するか否か判断する

build.gradle の ruleSets に指定する RuleSet を1つだけにして clean タスク → Rebuild Project → build タスク の順に実行し、以下の方針で判断します。

  • Web で PMD を設定している build.gradle を調べてみると java-basic, java-braces の2つを適用している例がよく見られたので、この2つは必ず適用することにします。ただしメッセージが出力されるのか否かは確認します。
  • それ以外は出力されるメッセージと PMD Rulesets index: Current Rulesets のマニュアルでチェックされる内容を確認して、適用するか否かを判断します。

また適用の方法については、最終的には build.gradle の ruleSets に指定する方法ではなく、別の xml ファイルで細かく条件を指定する方法に変更します。作成する xml ファイルは /config/pmd/pmd-project-rulesets.xml とし、以下の内容のファイルに RuleSet を追加していきます。

<?xml version="1.0"?>
<ruleset name="mybraces"
         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>custom rulesets</description>

    .....(ここに RuleSet を記述します).....

</ruleset>

java-basic

java-basic は何もメッセージは出ませんでした。これはそのまま適用します。

    <rule ref="rulesets/java/basic.xml"/>

java-braces

java-braces は何もメッセージは出ませんでした。これはそのまま適用します。

    <rule ref="rulesets/java/braces.xml"/>

java-clone

java-clone は何もメッセージは出ませんでした。

Clone Implementation でチェック内容を確認すると適用しても問題なさそうだったので、そのまま適用することにします。

    <rule ref="rulesets/java/clone.xml"/>

java-codesize

java-codesize は 2 PMD rule violations were found. という結果でした。メッセージの種類は1種類で、以下のメッセージでした。

  • This class has too many methods, consider refactoring it.

Code Size でチェック内容を確認した上で、以下のルールで適用することにします。

  • TooManyMethods(This class has too many methods, consider refactoring it.)は指摘されてもすぐに修正できなさそうなので、外します。
  • それ以外はそのまま適用します。
    <rule ref="rulesets/java/codesize.xml">
        <exclude name="TooManyMethods"/>
    </rule>

java-comments

java-comments は 479 PMD rule violations were found. という結果でした。メッセージの種類は8種類で、以下のメッセージでした。

  • headerCommentRequirement Required
  • fieldCommentRequirement Required
  • Comment is too large: Line too long
  • publicMethodCommentRequirement Required
  • protectedMethodCommentRequirement Required
  • To avoid mistakes add a comment at the beginning of the ... field if you want a default access modifier
  • Comment is too large: Too many lines
  • enumCommentRequirement Required

Comments でチェック内容を確認した上で、以下のルールで適用することにします。

  • CommentRequired の headerCommentRequirement(headerCommentRequirement Required)だけ指摘して欲しいと思ったので(checkstyle でクラスのコメントがないのをチェックできていないことに気付いたので)、これだけ適用します。
    <rule ref="rulesets/java/comments.xml/CommentRequired">
        <properties>
            <property name="fieldCommentRequirement" value="Ignored"/>
            <property name="publicMethodCommentRequirement" value="Ignored"/>
            <property name="protectedMethodCommentRequirement" value="Ignored"/>
            <property name="enumCommentRequirement" value="Ignored"/>
        </properties>
    </rule>

java-controversial

java-controversial は 169 PMD rule violations were found. という結果でした。メッセージの種類は12種類で、以下のメッセージでした。

  • Each class should declare at least one constructor
  • Avoid unnecessary constructors - the compiler will generate these for you
  • It is a good practice to call super() in a constructor
  • Use explicit scoping instead of the default package private level
  • Found 'DD'-anomaly for variable ...
  • Found 'DU'-anomaly for variable ...
  • If you run in Java5 or newer and have concurrent access, you should use the ConcurrentHashMap implementation
  • A method should have only one exit point, and that should be the last statement in the method
  • Found 'UR'-anomaly for variable ...
  • Avoid using Literals in Conditional Statements
  • This statement may have some unnecessary parentheses
  • Assigning an Object to null is a code smell. Consider refactoring.

Controversial でチェック内容を確認しましたが、この RuleSet に必要性を感じなかったので、適用しないことにします。

java-coupling

java-coupling は 247 PMD rule violations were found. という結果でした。メッセージの種類は3種類で、以下のメッセージでした。またこの RuleSets を適用すると Removed misconfigured rule: LoosePackageCoupling cause: No packages or classes specified のメッセージも表示されました。

  • Potential violation of Law of Demeter (method chain calls)
  • Potential violation of Law of Demeter (object not created locally)
  • Potential violation of Law of Demeter (static property access)

Coupling でチェック内容を確認しましたが、この RuleSet に必要性を感じなかったので、適用しないことにします。

java-design

java-design は 55 PMD rule violations were found. という結果でした。メッセージの種類は11種類で、以下のメッセージでした。

  • All methods are static. Consider using a utility class instead. Alternatively, you could add a private constructor or make the class abstract to silence this warning.
  • Document empty method body
  • Consider using varargs for methods or constructors which take an array the last parameter.
  • Consider simply returning the value vs storing it in local variable '...'
  • Document empty constructor
  • Private field '...' could be made final; it is only initialized in the declaration or constructor.
  • Avoid autogenerated methods to access private fields and methods of inner / outer classes
  • New exception is thrown in catch block, original stack trace may be lost
  • A class which only has private constructors should be final
  • Class cannot be instantiated and does not provide any static methods or fields
  • Deeply nested if..then statements are hard to read

Design でチェック内容を確認した上で、以下のルールで適用することにします。

  • UseUtilityClassAll methods are static. Consider using a utility class instead. Alternatively, you could add a private constructor or make the class abstract to silence this warning.)は Application.javaSpring Framework の @Component アノテーションを付加していて Helper クラスにしているものが検知されてしまうので、外します。
  • UncommentedEmptyMethodBodyDocument empty method body)は @Aspect を付加したクラスの @Pointcut アノテーションを付加したメソッドが検知されていたので、外します。
  • MissingStaticMethodInNonInstantiatableClassClass cannot be instantiated and does not provide any static methods or fields)は ValuesHelper クラスが検知されていて修正のしようがないので、外します。
  • それ以外はそのまま適用します。
    <rule ref="rulesets/java/design.xml">
        <exclude name="UseUtilityClass"/>
        <exclude name="UncommentedEmptyMethodBody"/>
        <exclude name="MissingStaticMethodInNonInstantiatableClass"/>
    </rule>

java-empty

java-empty は何もメッセージは出ませんでした。

Empty Code でチェック内容を確認すると指摘してもらいたい点が多かったので、そのまま適用することにします。

    <rule ref="rulesets/java/empty.xml"/>

java-finalizers

java-finalizers は何もメッセージは出ませんでした。

Finalizer でチェック内容を確認すると適用しても問題なさそうだったので、そのまま適用することにします。

    <rule ref="rulesets/java/finalizers.xml"/>

java-imports

java-design は 55 PMD rule violations were found. という結果でした。メッセージの種類は1種類で、以下のメッセージでした。

  • Unnecessary use of fully qualified name ... due to existing import ...

Import Statements でチェック内容を確認すると適用しても問題なさそうだったので、そのまま適用することにします。

    <rule ref="rulesets/java/imports.xml"/>

java-logging-jakarta-commons

java-logging-jakarta-commons は 2 PMD rule violations were found. という結果でした。メッセージの種類は1種類で、以下のメッセージでした。

  • There is log block not surrounded by if

Jakarta Commons Logging でチェック内容を確認すると指摘して欲しい点が記載されているのですが、試してみると期待通り動作しないようです。

  • There is log block not surrounded by if が出力されたところは確かに logger.info(...) しか記述しておらず if (logger.isInfoEnabled()) { ... } は記述していなかったのですが、他に logger.info(...) しか記述していないところでメッセージが出ていない箇所があります。
  • GuardDebugLogging の rule は検知して欲しいと思ったのですが、logger.debug(...) だけ記述してもメッセージが何も表示されませんでした。

org.slf4j.Logger を使用しているからでしょうか。。。? 動作していないようなので、外すことにします。

java-logging-java

java-logging-java7 PMD rule violations were found. という結果でした。メッセージの種類は1種類で、以下のメッセージでした。

  • The Logger variable declaration does not contain the static and final modifiers

Java Logging でチェック内容を確認すると適用しても問題なさそうだったので、そのまま適用することにします。

    <rule ref="rulesets/java/logging-java.xml"/>

java-naming

java-naming は 175 PMD rule violations were found. という結果でした。メッセージの種類は1種類で、以下のメッセージでした。

  • Variables that are final and static should be all capitals, ... is not all capitals.
  • Avoid excessively long variable names like ...
  • Avoid variables with short names like ...
  • Only variables that are final should contain underscores (except for underscores in standard prefix/suffix), ... is not final.
  • The field name indicates a constant but its modifiers do not
  • Variables should start with a lowercase character, ... starts with uppercase character.
  • Avoid short class names like ...

Naming でチェック内容を確認した上で、以下のルールで適用することにします。

  • 以下の rule は必要性を感じなかったので外します。
    • ShortVariable(Avoid variables with short names like ...
    • LongVariable(Avoid excessively long variable names like ...
    • ShortMethodName
    • ShortClassName(Avoid short class names like ...
  • それ以外はそのまま適用します。
    <rule ref="rulesets/java/naming.xml">
        <exclude name="ShortVariable"/>
        <exclude name="LongVariable"/>
        <exclude name="ShortMethodName"/>
        <exclude name="ShortClassName"/>
    </rule>

java-optimizations

java-optimizations は 527 PMD rule violations were found. という結果でした。メッセージの種類は6種類で、以下のメッセージでした。

  • Parameter ... is not assigned and could be declared final
  • Local variable ... could be declared final
  • Avoid declaring a variable if it is unreferenced before a possible exit point.
  • Avoid instantiating new objects inside loops
  • Prefer StringBuffer over += for concatenating strings
  • Avoid using redundant field initializer for ...

Optimization でチェック内容を確認した上で、以下のルールで適用することにします。

  • 以下の2つの rule はそこまで final だらけにしたくないと思ったので、外します。
    • MethodArgumentCouldBeFinal(Parameter ... is not assigned and could be declared final
    • LocalVariableCouldBeFinal(Local variable ... could be declared final
  • AvoidInstantiatingObjectsInLoops(Avoid instantiating new objects inside loops)は適用しますが、CSV ファイルのレコードをループでチェックしている処理の中の errors.reject(..., new Object[]{...}, ...) のように指摘を受けても修正しようがない箇所もあったので、その場合には @SuppressWarnings({PMD.AvoidInstantiatingObjectsInLoops}) アノテーションを付加して PMD のチェックが行われないようにします。
  • UseStringBufferForStringAppends(Prefer StringBuffer over += for concatenating strings) は、簡単な文字列結合でも指摘を受けていて、さすがにそこまで全部 StringBuffer で処理したくないので外します。
  • RedundantFieldInitializer(Avoid using redundant field initializer for ...)は入れた方がよいのか否かちょっと悩みましたが、例えデフォルトでも明示的に書きたい場合もあると思ったので、外すことにします。
    <rule ref="rulesets/java/optimizations.xml">
        <exclude name="LocalVariableCouldBeFinal"/>
        <exclude name="MethodArgumentCouldBeFinal"/>
        <exclude name="UseStringBufferForStringAppends"/>
        <exclude name="RedundantFieldInitializer"/>
    </rule>

java-strictexception

java-strictexception は 14 PMD rule violations were found. という結果でした。メッセージの種類は3種類で、以下のメッセージでした。

  • A method/constructor shouldnt explicitly throw java.lang.Exception
  • Avoid throwing raw exception types.
  • Avoid catching generic exceptions such as NullPointerException, RuntimeException, Exception in try-catch block

Strict Exceptions でチェック内容を確認した上で、以下のルールで適用することにします。

  • SignatureDeclareThrowsException(A method/constructor shouldnt explicitly throw java.lang.Exception)は throws Exception としか書きようがないところまで指摘されていたので、外します。
  • AvoidThrowingRawExceptionTypes(Avoid throwing raw exception types.)は RuntimeException ではなくてきちんと場面に応じた例外を throw しようという指摘なのですが、安直に RuntimeException を使いたい時もあるので、外すことにします。
  • AvoidCatchingGenericException(Avoid catching generic exceptions such as NullPointerException, RuntimeException, Exception in try-catch block)も Exception を catch したい時があるので外します。
  • それ以外はそのまま適用します。
    <rule ref="rulesets/java/strictexception.xml">
        <exclude name="SignatureDeclareThrowsException"/>
        <exclude name="AvoidThrowingRawExceptionTypes"/>
        <exclude name="AvoidCatchingGenericException"/>
    </rule>

java-strings

java-strings は 30 PMD rule violations were found. という結果でした。メッセージの種類は3種類で、以下のメッセージでした。

  • StringBuffer (or StringBuilder).append is called consecutively without reusing the target variable.
  • Avoid appending characters as strings in StringBuffer.append.
  • The String literal ... appears ... times in this file; the first occurrence is on line ...

String and StringBuffer でチェック内容を確認すると適用しても問題なさそうだったので、そのまま適用することにします。

    <rule ref="rulesets/java/strings.xml"/>

java-sunsecure

java-sunsecure は何もメッセージは出ませんでした。

Security Code Guidelines でチェック内容を確認すると適用しても問題なさそうだったので、そのまま適用することにします。

    <rule ref="rulesets/java/sunsecure.xml"/>

java-typeresolution

java-typeresolution は 6 PMD rule violations were found. という結果でした。メッセージの種類は1種類で、以下のメッセージでした。

  • A method/constructor shouldnt explicitly throw java.lang.Exception

Type Resolution でチェック内容を確認した上で、以下のルールで適用することにします。

  • SignatureDeclareThrowsException(A method/constructor shouldnt explicitly throw java.lang.Exception)は削除できない throws Exception を指摘されていたので、外します。
  • それ以外の rule は適用します。
    <rule ref="rulesets/java/typeresolution.xml">
        <exclude name="SignatureDeclareThrowsException"/>
    </rule>

java-unnecessary

java-unnecessary は 41 PMD rule violations were found. という結果でした。メッセージの種類は2種類で、以下のメッセージでした。

  • Avoid modifiers which are implied by the context
  • Useless parentheses.

Unnecessary でチェック内容を確認した上で、 以下のルールで適用することにします。

  • UselessParentheses(Useless parentheses.)は削除できない箇所を指摘されていたので、外します。
  • それ以外の rule は適用します。
    <rule ref="rulesets/java/unnecessary.xml">
        <exclude name="UselessParentheses"/>
    </rule>

java-unusedcode

java-unnecessary は 6 PMD rule violations were found. という結果でした。メッセージの種類は2種類で、以下のメッセージでした。

  • Avoid unused private methods such as ...
  • Avoid unused local variables such as ...

Unused Code でチェック内容を確認した上で、以下のルールで適用することにします。

  • この RuleSet はそのまま適用します。
  • メッセージが出力された箇所で指摘を受ける必要がないところは @SuppressWarnings({...}) アノテーションを付加して PMD のチェックが行われないようにします。
    <rule ref="rulesets/java/unusedcode.xml"/>

pmd-project-rulesets.xml を作成し、build.gradle を変更する

  1. /config/pmd/pmd-project-rulesets.xml を新規作成し、リンク先の内容 を記述します。

  2. build.gradle を リンク先のその2の内容 に変更します。

再び build タスクを実行する

  1. clean タスク → Rebuild Project → build タスク の順に実行します。

    今度は 219 PMD rule violations were found. という結果でした。

    f:id:ksby:20170630053245p:plain

続きます。。。

次回、指摘を受けた箇所を修正します。また今回記事を書き始めた時は PMD のバージョンは 5.7.0 だったのですが、その後で 5.8.0 が出たようです。5.8.0 に変更して確認しながら修正します。

ソースコード

build.gradle

■その1

..........

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'de.undercouch.download'
apply plugin: 'groovy'
apply plugin: 'net.ltgt.errorprone'
apply plugin: 'checkstyle'
apply plugin: 'findbugs'
apply plugin: 'pmd'

..........

pmd {
    toolVersion = "5.7.0"
    sourceSets = [project.sourceSets.main]
    ignoreFailures = true
    consoleOutput = true
    ruleSets = [
            // ruleSet の種類・説明は 以下の URL 参照
            // https://github.com/pmd/pmd/tree/master/pmd-java/src/main/resources/rulesets/java
            // https://pmd.github.io/pmd-5.7.0/pmd-java/rules/index.html
            'java-basic'
            , 'java-braces'
            , 'java-clone'
            , 'java-codesize'
            , 'java-comments'
            , 'java-controversial'
            , 'java-coupling'
            , 'java-design'
            , 'java-empty'
            , 'java-finalizers'
            , 'java-imports'
            , 'java-logging-jakarta-commons'
            , 'java-logging-java'
            , 'java-migrating'
            , 'java-naming'
            , 'java-optimizations'
            , 'java-strictexception'
            , 'java-strings'
            , 'java-sunsecure'
            , 'java-typeresolution'
            , 'java-unnecessary'
            , 'java-unusedcode'
    ]
}
  • apply plugin: 'pmd' を追加します。
  • pmd { ... } を追加します。ruleSets は java-j2ee, java-javabeans, java-junit, java-migrating を除き一旦全部入れています。

■その2

pmd {
    toolVersion = "5.7.0"
    sourceSets = [project.sourceSets.main]
    ignoreFailures = true
    consoleOutput = true
    ruleSetFiles = rootProject.files("/config/pmd/pmd-project-rulesets.xml")
    ruleSets = []
}
  • ruleSetFiles = rootProject.files("/config/pmd/pmd-project-rulesets.xml") を追加します。
  • ruleSets = [] に変更します。

pmd-project-rulesets.xml

<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="mybraces"
         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>project rulesets</description>

    <!--
        rulesets の種類・説明は 以下の URL 参照
        https://github.com/pmd/pmd/tree/master/pmd-java/src/main/resources/rulesets/java
        https://pmd.github.io/pmd-5.7.0/pmd-java/rules/index.html
        ※"pmd-5.7.0" の部分は適用しているバージョンに変更すること。
    -->
    <rule ref="rulesets/java/basic.xml"/>
    <rule ref="rulesets/java/braces.xml"/>
    <rule ref="rulesets/java/clone.xml"/>
    <rule ref="rulesets/java/codesize.xml">
        <exclude name="TooManyMethods"/>
    </rule>
    <rule ref="rulesets/java/comments.xml/CommentRequired">
        <properties>
            <property name="fieldCommentRequirement" value="Ignored"/>
            <property name="publicMethodCommentRequirement" value="Ignored"/>
            <property name="protectedMethodCommentRequirement" value="Ignored"/>
            <property name="enumCommentRequirement" value="Ignored"/>
        </properties>
    </rule>
    <rule ref="rulesets/java/design.xml">
        <exclude name="UseUtilityClass"/>
        <exclude name="UncommentedEmptyMethodBody"/>
        <exclude name="MissingStaticMethodInNonInstantiatableClass"/>
    </rule>
    <rule ref="rulesets/java/empty.xml"/>
    <rule ref="rulesets/java/finalizers.xml"/>
    <rule ref="rulesets/java/imports.xml"/>
    <rule ref="rulesets/java/logging-java.xml"/>
    <rule ref="rulesets/java/naming.xml">
        <exclude name="ShortVariable"/>
        <exclude name="LongVariable"/>
        <exclude name="ShortMethodName"/>
        <exclude name="ShortClassName"/>
    </rule>
    <rule ref="rulesets/java/optimizations.xml">
        <exclude name="LocalVariableCouldBeFinal"/>
        <exclude name="MethodArgumentCouldBeFinal"/>
        <exclude name="UseStringBufferForStringAppends"/>
        <exclude name="RedundantFieldInitializer"/>
    </rule>
    <rule ref="rulesets/java/strictexception.xml">
        <exclude name="SignatureDeclareThrowsException"/>
        <exclude name="AvoidThrowingRawExceptionTypes"/>
        <exclude name="AvoidCatchingGenericException"/>
    </rule>
    <rule ref="rulesets/java/strings.xml"/>
    <rule ref="rulesets/java/sunsecure.xml"/>
    <rule ref="rulesets/java/typeresolution.xml">
        <exclude name="SignatureDeclareThrowsException"/>
    </rule>
    <rule ref="rulesets/java/unnecessary.xml">
        <exclude name="UselessParentheses"/>
    </rule>
    <rule ref="rulesets/java/unusedcode.xml"/>
</ruleset>

履歴

2017/06/30
初版発行。