1. 概要
開発中に、使用するよりも多くの依存関係を追加してしまうことがあります。
このクイックチュートリアルでは、Gradle Nebula Lint プラグインを使用して、このような問題を特定して修正する方法を説明します。
2. セットアップと構成
この例では、マルチモジュールのGradle5セットアップを使用しています。
このプラグインはGroovyベースのビルドファイルでのみ機能します。
ルートプロジェクトビルドファイルで設定しましょう。
plugins {
id "nebula.lint" version "16.9.0"
}
description = "Gradle 5 root project"
allprojects {
apply plugin :"java"
apply plugin :"nebula.lint"
gradleLint {
rules=['unused-dependency']
}
group = "com.baeldung"
version = "0.0.1"
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
repositories {
jcenter()
}
}
当面は、マルチプロジェクトビルドに対してのみこの方法で構成できます。 これは、各モジュールに個別に適用できないことを意味します。
次に、モジュールの依存関係を構成しましょう。
description = "Gradle Unused Dependencies example"
dependencies {
implementation('com.google.guava:guava:29.0-jre')
testImplementation('junit:junit:4.12')
}
次に、モジュールソースに簡単なメインクラスを追加しましょう。
public class UnusedDependencies {
public static void main(String[] args) {
System.out.println("Hello world");
}
}
これを少し後で構築し、プラグインがどのように機能するかを確認します。
3. 検出シナリオとレポート
プラグインは出力jarを検索して、依存関係が使用されているかどうかを検出します。
ただし、いくつかの条件に応じて、異なる結果が得られる可能性があります。
次のセクションでは、より興味深いケースについて説明します。
3.1. 未使用の依存関係
セットアップが完了したので、基本的なユースケースを見てみましょう。 未使用の依存関係に関心があります。
lintGradleタスクを実行してみましょう。
$ ./gradlew lintGradle
> Task :lintGradle FAILED
# failure output omitted
warning unused-dependency this dependency is unused and can be removed
unused-dependencies/build.gradle:6
implementation('com.google.guava:guava:29.0-jre')
✖ 1 problem (0 errors, 1 warning)
To apply fixes automatically, run fixGradleLint, review, and commit the changes.
# some more failure output
何が起きたのか見てみましょう。 compileClasspath 構成には、未使用の依存関係( guava )があります。
プラグインが示唆するようにfixGradleLintタスクを実行すると、依存関係はbuild.gradleから自動的に削除されます。
ただし、代わりに依存関係のあるダミーロジックを使用しましょう。
public static void main(String[] args) {
System.out.println("Hello world");
useGuava();
}
private static void useGuava() {
List<String> list = ImmutableList.of("Baledung", "is", "cool");
System.out.println(list.stream().collect(Collectors.joining(" ")));
}
再実行しても、エラーは発生しません。
$ ./gradlew lintGradle
BUILD SUCCESSFUL in 559ms
3 actionable tasks: 1 executed, 2 up-to-date
3.2. 推移的な依存関係の使用
別の依存関係を含めましょう:
dependencies {
implementation('com.google.guava:guava:29.0-jre')
implementation('org.apache.httpcomponents:httpclient:4.5.12')
testImplementation('junit:junit:4.12')
}
今回は、推移的な依存関係から何かを使用しましょう。
public static void main(String[] args) {
System.out.println("Hello world");
useGuava();
useHttpCore();
}
// other methods
private static void useHttpCore() {
SSLContextBuilder.create();
}
しばらく様子を見てみましょう:
$ ./gradlew lintGradle
> Task :lintGradle FAILED
# failure output omitted
warning unused-dependency one or more classes in org.apache.httpcomponents:httpcore:4.4.13
are required by your code directly (no auto-fix available)
warning unused-dependency this dependency is unused and can be removed
unused-dependencies/build.gradle:8
implementation('org.apache.httpcomponents:httpclient:4.5.12')
✖ 2 problems (0 errors, 2 warnings)
2つのエラーが発生します。 最初のエラーは、httpcoreを直接参照する必要があることを大まかに示しています。
サンプルのSSLContextBuilderは実際にはその一部です。
2番目のエラーは、httpclient。から何も使用していないことを示しています
推移的な依存関係を使用する場合、プラグインはそれを直接的な依存関係にするように指示します。
依存関係ツリーを見てみましょう。
$ ./gradlew unused-dependencies:dependencies --configuration compileClasspath
> Task :unused-dependencies:dependencies
------------------------------------------------------------
Project :unused-dependencies - Gradle Unused Dependencies example
------------------------------------------------------------
compileClasspath - Compile classpath for source set 'main'.
+--- com.google.guava:guava:29.0-jre
| +--- com.google.guava:failureaccess:1.0.1
| +--- com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
| +--- com.google.code.findbugs:jsr305:3.0.2
| +--- org.checkerframework:checker-qual:2.11.1
| +--- com.google.errorprone:error_prone_annotations:2.3.4
| \--- com.google.j2objc:j2objc-annotations:1.3
\--- org.apache.httpcomponents:httpclient:4.5.12
+--- org.apache.httpcomponents:httpcore:4.4.13
+--- commons-logging:commons-logging:1.2
\--- commons-codec:commons-codec:1.11
この場合、httpcoreがhttpclientによって取り込まれていることがわかります。
3.3. リフレクションでの依存関係の使用
リフレクションを使用する場合はどうですか?
この例を少し強化してみましょう。
public static void main(String[] args) {
System.out.println("Hello world");
useGuava();
useHttpCore();
useHttpClientWithReflection();
}
// other methods
private static void useHttpClientWithReflection() {
try {
Class<?> httpBuilder = Class.forName("org.apache.http.impl.client.HttpClientBuilder");
Method create = httpBuilder.getMethod("create", null);
create.invoke(httpBuilder, null);
} catch (Exception e) {
e.printStackTrace();
}
}
次に、Gradleタスクを再実行しましょう。
$ ./gradlew lintGradle
> Task :lintGradle FAILED
# failure output omitted
warning unused-dependency one or more classes in org.apache.httpcomponents:httpcore:4.4.13
are required by your code directly (no auto-fix available)
warning unused-dependency this dependency is unused and can be removed
unused-dependencies/build.gradle:9
implementation('org.apache.httpcomponents:httpclient:4.5.12')
✖ 2 problems (0 errors, 2 warnings)
どうしたの? 依存関係(httpclient)から HttpClientBuilder を使用しましたが、それでもエラーが発生しました。
リフレクション付きのライブラリを使用する場合、プラグインはその使用法を検出しません。
その結果、同じ2つのエラーが表示されます。
一般に、runtimeOnlyなどの依存関係を構成する必要があります。
3.4. レポートの生成
大規模なプロジェクトの場合、端末で返されるエラーの数は処理が困難になります。
代わりにレポートを提供するようにプラグインを構成しましょう。
allprojects {
apply plugin :"java"
apply plugin :"nebula.lint"
gradleLint {
rules=['unused-dependency']
reportFormat = 'text'
}
// other details omitted
}
generateGradleLintReportタスクを実行して、ビルド出力を確認しましょう。
$ ./gradlew generateGradleLintReport
# task output omitted
$ cat unused-dependencies/build/reports/gradleLint/unused-dependencies.txt
CodeNarc Report - Jun 20, 2020, 3:25:28 PM
Summary: TotalFiles=1 FilesWithViolations=1 P1=0 P2=3 P3=0
File: /home/user/tutorials/gradle-5/unused-dependencies/build.gradle
Violation: Rule=unused-dependency P=2 Line=null Msg=[one or more classes in org.apache.httpcomponents:httpcore:4.4.13
are required by your code directly]
Violation: Rule=unused-dependency P=2 Line=9 Msg=[this dependency is unused and can be removed]
Src=[implementation('org.apache.httpcomponents:httpclient:4.5.12')]
Violation: Rule=unused-dependency P=2 Line=17 Msg=[this dependency is unused and can be removed]
Src=[testImplementation('junit:junit:4.12')]
[CodeNarc (http://www.codenarc.org) v0.25.2]
これで、testCompileClasspath構成の未使用の依存関係が検出されます。
残念ながら、これはプラグインの動作に一貫性がありません。 その結果、3つのエラーが発生します。
4. 結論
このチュートリアルでは、Gradleビルドで未使用の依存関係を見つける方法を説明しました。
まず、一般的な設定について説明しました。 その後、さまざまな依存関係とその使用法で報告されたエラーを調査しました。
最後に、テキストベースのレポートを生成する方法を見ました。
いつものように、完全なコードサンプルはGitHubで見つけることができます。