コンパイル
結果の
バイトコード
と合わせて
ソースコード
を解析します。
ルールに基づいてコーディングミスを発見します。
(たとえば
null
を代入した変数にアクセスしてる、など)
不正なコード記述を検出する
CheckStyle
github.com/spring.io/spring-javaformat
ルールに基づいて不正なコード記述を発見します。
SonarQube は?
Code Quality and Security | SonarQube
デプロイしたサービスに
ソースコード
の解析結果とかを蓄積する形態のプロダクトです。
静的解析としてやりたいことはだいたいできる感じになっています。
ユーザーやグループによる認証認可、プロジェクトという管理単位もあるので、プロジェクトごとに用意するより複数のプロジェクトで共有するほうが効率的じゃないかなと思います。
そういう理由でこの説明では紹介してません。
参考プロジェクトとして
spring-petclinic
に記述を追加しました。
ビルドツール
maven-pmd-plugin
javancss-
maven
-plugin
×
Maven
プラグイン
がダウンロードできない
jQAssistant
jQAssistant Java Metris Plugin
×
Maven
プラグイン
がダウンロードできない
spotbugs-maven-plugin
maven-checkstyle-plugin
spring-io/spring-javaformat
× レポートが出ない
環境によってはクラスローダーの都合で実行時エラーになるため、
ワークアラウンド
で
システムプロ
パティ
jdk.net.URLClassPath.disableClassPathURLCheck
を追加します
useSystemClassLoader
では制御できない部分の問題です
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-surefire-plugin
</artifactId>
<version>
3.0.0-M5
</version>
</plugin>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-surefire-report-plugin
</artifactId>
<version>
3.0.0-M5
</version>
</plugin>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-site-plugin
</artifactId>
<version>
3.9.1
</version>
</plugin>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-project-info-reports-plugin
</artifactId>
<version>
3.1.0
</version>
</plugin>
<plugin>
<groupId>
io.spring.javaformat
</groupId>
<artifactId>
spring-javaformat-maven-plugin
</artifactId>
<version>
0.0.24
</version>
</plugin>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-pmd-plugin
</artifactId>
<version>
3.13.0
</version>
</plugin>
<plugin>
<groupId>
com.github.spotbugs
</groupId>
<artifactId>
spotbugs-maven-plugin
</artifactId>
<version>
4.0.4
</version>
</plugin>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-checkstyle-plugin
</artifactId>
<version>
3.1.1
</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-checkstyle-plugin
</artifactId>
<dependencies>
<dependency>
<groupId>
com.puppycrawl.tools
</groupId>
<artifactId>
checkstyle
</artifactId>
<version>
[8.32,)
</version>
</dependency>
<dependency>
<groupId>
io.spring.nohttp
</groupId>
<artifactId>
nohttp-checkstyle
</artifactId>
<version>
[0.0.4.RELEASE,)
</version>
</dependency>
<dependency>
<groupId>
io.spring.javaformat
</groupId>
<artifactId>
spring-javaformat-checkstyle
</artifactId>
<version>
[0.0.24,)
</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>
nohttp-checkstyle-validation
</id>
<phase>
validate
</phase>
<configuration>
<configLocation>
src/checkstyle/nohttp-checkstyle.xml
</configLocation>
<suppressionsLocation>
src/checkstyle/nohttp-checkstyle-suppressions.xml
</suppressionsLocation>
<encoding>
${project.build.sourceEncoding}
</encoding>
<sourceDirectories>
${project.basedir}
</sourceDirectories>
<includes>
**/*
</includes>
<excludes>
**/.git/**/*,**/.idea/**/*,**/target/**/,**/.flattened-pom.xml,**/*.class
</excludes>
<failsOnError>
false
</failsOnError>
<failOnViolation>
false
</failOnViolation>
</configuration>
<goals>
<goal>
check
</goal>
</goals>
</execution>
<execution>
<id>
javaformat-validation
</id>
<phase>
validate
</phase>
<inherited>
true
</inherited>
<configuration>
<configLocation>
io/spring/javaformat/checkstyle/checkstyle.xml
</configLocation>
<includeTestSourceDirectory>
true
</includeTestSourceDirectory>
<failsOnError>
false
</failsOnError>
<failOnViolation>
false
</failOnViolation>
</configuration>
<goals>
<goal>
check
</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-surefire-plugin
</artifactId>
<configuration>
<argLine>
-Djdk.net.URLClassPath.disableClassPathURLCheck=true
</argLine>
</configuration>
</plugin>
<plugin>
<groupId>
org.jacoco
</groupId>
<artifactId>
jacoco-maven-plugin
</artifactId>
<version>
${jacoco.version}
</version>
<executions>
<execution>
<goals>
<goal>
prepare-agent
</goal>
</goals>
</execution>
<execution>
<id>
report
</id>
<phase>
prepare-package
</phase>
<goals>
<goal>
report
</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-site-plugin
</artifactId>
<executions>
<execution>
<id>
attach-descriptor
</id>
<goals>
<goal>
attach-descriptor
</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-pmd-plugin
</artifactId>
<executions>
<execution>
<goals>
<goal>
check
</goal>
<goal>
cpd-check
</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>
central
</id>
<name>
central
</name>
<url>
https://repo1.maven.org/maven2/
</url>
<snapshots>
<enabled>
false
</enabled>
</snapshots>
<releases>
<enabled>
true
</enabled>
</releases>
</repository>
<repository>
<id>
spring-snapshots
</id>
<name>
Spring Snapshots
</name>
<url>
https://repo.spring.io/snapshot
</url>
<snapshots>
<enabled>
true
</enabled>
</snapshots>
</repository>
<repository>
<id>
spring-milestones
</id>
<name>
Spring Milestones
</name>
<url>
https://repo.spring.io/milestone
</url>
<snapshots>
<enabled>
false
</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>
central
</id>
<name>
central
</name>
<url>
https://repo1.maven.org/maven2/
</url>
<snapshots>
<enabled>
false
</enabled>
</snapshots>
<releases>
<enabled>
true
</enabled>
</releases>
</pluginRepository>
<pluginRepository>
<id>
spring-snapshots
</id>
<name>
Spring Snapshots
</name>
<url>
https://repo.spring.io/snapshot
</url>
<snapshots>
<enabled>
true
</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>
spring-milestones
</id>
<name>
Spring Milestones
</name>
<url>
https://repo.spring.io/milestone
</url>
<snapshots>
<enabled>
false
</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<reporting>
<plugins>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-project-info-reports-plugin
</artifactId>
<reportSets>
<reportSet>
<reports>
<report>
index
</report>
<report>
licenses
</report>
<report>
modules
</report>
<report>
dependencies
</report>
<report>
plugins
</report>
<report>
dependency-info
</report>
<report>
dependency-management
</report>
<report>
plugin-management
</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-pmd-plugin
</artifactId>
<configuration>
<language>
java
</language>
<rulesets>
<ruleset>
/category/java/bestpractices.xml
</ruleset>
<ruleset>
/category/java/codestyle.xml
</ruleset>
<ruleset>
/category/java/design.xml
</ruleset>
<ruleset>
/category/java/documentation.xml
</ruleset>
<ruleset>
/category/java/errorprone.xml
</ruleset>
<ruleset>
/category/java/multithreading.xml
</ruleset>
<ruleset>
/category/java/performance.xml
</ruleset>
<ruleset>
/category/java/security.xml
</ruleset>
</rulesets>
<aggregate>
true
</aggregate>
<outputDirectory>
${project.reporting.outputDirectory}
</outputDirectory>
<targetDirectory>
${project.build.directory}
</targetDirectory>
<sourceEncoding>
${project.build.sourceEncoding}
</sourceEncoding>
<outputEncoding>
${project.reporting.outputEncoding}
</outputEncoding>
<targetJdk>
${maven.compiler.source}
</targetJdk>
<failOnViolation>
false
</failOnViolation>
<verbose>
true
</verbose>
<format>
html
</format>
</configuration>
<reportSets>
<reportSet>
<reports>
<report>
pmd
</report>
<report>
cpd
</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-checkstyle-plugin
</artifactId>
<configuration>
<configLocation>
src/checkstyle/google_checks.xml
</configLocation>
<encoding>
${project.build.sourceEncoding}
</encoding>
<consoleOutput>
false
</consoleOutput>
<failOnViolation>
false
</failOnViolation>
<failsOnError>
false
</failsOnError>
<linkXRef>
false
</linkXRef>
</configuration>
<reportSets>
<reportSet>
<reports>
<report>
checkstyle
</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>
com.github.spotbugs
</groupId>
<artifactId>
spotbugs-maven-plugin
</artifactId>
<reportSets>
<reportSet>
<reports>
<report>
spotbugs
</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-surefire-report-plugin
</artifactId>
</plugin>
</plugins>
</reporting>
github.com/spotbugs/spotbugs-gradle-plugin
The Checkstyle Plugin
spring-io/spring-javaformat
× Gradle
プラグイン
はない
'category/java/bestpractices.xml'
,
'category/java/codestyle.xml'
,
'category/java/design.xml'
,
'category/java/documentation.xml'
,
'category/java/errorprone.xml'
,
'category/java/multithreading.xml'
,
'category/java/performance.xml'
,
'category/java/security.xml'
,
tasks.withType(Pmd) {
reports {
html.enabled =
true
xml.enabled =
false
checkstyle {
ignoreFailures =
true
reportsDir = file(
"
$buildDir
/checkstyle"
)
configFile = file(
'src/checkstyle/google_checks.xml'
)
toolVersion =
'8.29'
tasks.withType(Checkstyle) {
reports {
html.enabled =
true
xml.enabled =
false
spotbugs {
ignoreFailures =
true
reportsDir = file(
"
$buildDir
/spotbugs"
)
tasks.withType(com.github.spotbugs.snom.SpotBugsTask) {
reports {
html.enabled =
true
xml.enabled =
false
ガイドを最新に保ち続けるのも面倒なので、必要な
プラグイン
を記述した
IntelliJ
の設定ファイルを
ソースコード
と一緒に
リポジトリ
へ配置しておくといいでしょう。
.idea/externalDependencies.xml
Settings > Build, Execution, Deployment > Required Plugins
の設定が格納されています
Required Plugins
は必須
プラグイン
を管理します
必須
プラグイン
が存在しない状態でプロジェクトをインポートすると、
IDE
が警告メッセージを表示します
Install required plugins
をクリックするだけでインストールできます
[./
intellij
-required-plugin-afford-to-install-plugin.
png
]
xml version="1.0" encoding="UTF-8"
<project version="4">
<component name="ExternalDependencies">
<plugin id="CheckStyle-IDEA" />
<plugin id="PMDPlugin" />
<plugin id="org.jetbrains.plugins.spotbugs" />
</component>
</project>
もう忘れた
いいのある?
実践ソフトウェアエンジニアリング(第9版)
Roger S. Pressman (著), Bruce R. Maxim (著), SEPA翻訳プロジェクト (翻訳), 西 康晴 (翻訳), 水野 昇幸 (翻訳), & 10 その他