Ongebruikte Gradle-afhankelijkheden zoeken

1. Overzicht

Soms kunnen we tijdens de ontwikkeling meer afhankelijkheden toevoegen dan we gebruiken.

In deze korte tutorial gaan we zien hoe we de Gradle Nebula Lint-plug-in kunnen gebruiken om dit soort problemen te identificeren en op te lossen.

2. Installatie en configuratie

We gebruiken een Gradle 5-opstelling met meerdere modules in onze voorbeelden.

Deze plug-in werkt alleen voor op Groovy gebaseerde build bestanden.

Laten we het configureren in het buildbestand van het rootproject:

plug-ins {id "nebula.lint" version "16.9.0"} description = "Gradle 5 root project" allprojects {plug-in toepassen: "java" plug-in toepassen: "nebula.lint" gradleLint {rules = ['ongebruikte-afhankelijkheid'] } group = "com.baeldung" version = "0.0.1" sourceCompatibility = "1.8" targetCompatibility = "1.8" opslagplaatsen {jcenter ()}}

We kunnen het voorlopig alleen op deze manier configureren voor builds met meerdere projecten. Dit betekent dat we het niet afzonderlijk in elke module kunnen toepassen.

Laten we vervolgens onze module-afhankelijkheden configureren:

description = "Gradle Unused Dependencies example" afhankelijkheden {implementatie ('com.google.guava: guava: 29.0-jre') testImplementation ('junit: junit: 4.12')}

Laten we nu een eenvoudige hoofdklasse toevoegen aan onze modulebronnen:

openbare klasse UnusedDependencies {openbare statische leegte hoofd (String [] args) {System.out.println ("Hallo wereld"); }}

We zullen hier later op voortbouwen en kijken hoe de plug-in werkt.

3. Detectiescenario's en rapporten

De plug-in doorzoekt de output jars om te detecteren of een afhankelijkheid wordt gebruikt of niet.

Echter, afhankelijk van verschillende omstandigheden kan het ons verschillende resultaten opleveren.

In de volgende secties zullen we de meer interessante gevallen onderzoeken.

3.1. Ongebruikte afhankelijkheden

Nu we onze setup hebben, laten we de basis use-case bekijken. We zijn geïnteresseerd in ongebruikte afhankelijkheden.

Laten we voer de ... uit lintGradle taak:

$ ./gradlew lintGradle> Taak: lintGradle FAILED # foutuitvoer weggelaten waarschuwing ongebruikte-afhankelijkheid deze afhankelijkheid is ongebruikt en kan worden verwijderd ongebruikte-afhankelijkheden / build.gradle: 6 implementatie ('com.google.guava: guava: 29.0-jre' ) ✖ 1 probleem (0 fouten, 1 waarschuwing) Om fixes automatisch toe te passen, voert u fixGradleLint uit, controleert u en legt u de wijzigingen vast. # nog wat foutuitvoer 

Laten we eens kijken wat er gebeurd is. We hebben een ongebruikte afhankelijkheid (guave) in onze compileClasspath configuratie.

Als wij rennen fixGradleLint taak zoals de plug-in suggereert, de afhankelijkheid wordt automatisch verwijderd uit onze build.gradle.

Laten we in plaats daarvan wat dummy-logica gebruiken met onze afhankelijkheid:

public static void main (String [] args) {System.out.println ("Hallo wereld"); useGuava (); } private static void useGuava () {List list = ImmutableList.of ("Baledung", "is", "cool"); System.out.println (list.stream (). Collect (Collectors.joining (""))); }

Als we het opnieuw uitvoeren, krijgen we geen fouten meer:

$ ./gradlew lintGradle SUCCESVOL BOUWEN in 559 ms 3 uitvoerbare taken: 1 uitgevoerd, 2 up-to-date

3.2. Transitieve afhankelijkheden gebruiken

Laten we nu een andere afhankelijkheid toevoegen:

afhankelijkheden {implementatie ('com.google.guava: guava: 29.0-jre') implementatie ('org.apache.httpcomponents: httpclient: 4.5.12') testImplementation ('junit: junit: 4.12')}

Laten we deze keer iets gebruiken van een transitieve afhankelijkheid:

public static void main (String [] args) {System.out.println ("Hallo wereld"); useGuava (); useHttpCore (); } // andere methoden privé statisch ongeldig useHttpCore () {SSLContextBuilder.create (); }

Laten we afwachten wat er gebeurt:

$ ./gradlew lintGradle> Taak: lintGradle FAILED # foutuitvoer weggelaten waarschuwing ongebruikte-afhankelijkheid een of meer klassen in org.apache. httpcomponents: httpcore: 4.4.13 zijn direct vereist door uw code (geen auto-fix beschikbaar) waarschuwing ongebruikt- afhankelijkheid deze afhankelijkheid is ongebruikt en kan worden verwijderd ongebruikte-afhankelijkheden / build.gradle: 8 implementatie ('org.apache.httpcomponents: httpclient: 4.5.12') ✖ 2 problemen (0 fouten, 2 waarschuwingen)

We krijgen twee fouten. De eerste fout zegt grofweg dat we moeten verwijzen httpcore direct.

De SSLContextBuilder in onze steekproef maakt er eigenlijk deel van uit.

De tweede fout zegt dat we niets gebruiken van httpclient.

Als we een transitieve afhankelijkheid gebruiken, vertelt de plug-in ons om er een directe te maken.

Laten we een kijkje nemen in onze afhankelijkheidsboom:

$ ./gradlew ongebruikte-afhankelijkheden: afhankelijkheden --configuratie compileClasspath> Taak: ongebruikte-afhankelijkheden: afhankelijkheden ----------------------------- ------------------------------- Project: unused-dependencies - Voorbeeld van Gradle Unused Dependencies --------- -------------------------------------------------- - compileClasspath - Compileer klassenpad voor bronset 'main'. + --- com.google.guava: guava: 29.0-jre | + --- com.google.guava: failureaccess: 1.0.1 | + --- com.google.guava: listenablefuture: 9999.0-leeg-om-conflict-met-guave-te-vermijden | + --- 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-annotaties: 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

In dit geval kunnen we dat zien httpcore wordt binnengebracht door httpclient.

3.3. Afhankelijkheden gebruiken met reflectie

Hoe zit het als we reflectie gebruiken?

Laten we ons voorbeeld een beetje verbeteren:

public static void main (String [] args) {System.out.println ("Hallo wereld"); useGuava (); useHttpCore (); useHttpClientWithReflection (); } // andere methoden privé statisch ongeldig useHttpClientWithReflection () {probeer {Class httpBuilder = Class.forName ("org.apache.http.impl.client.HttpClientBuilder"); Methode create = httpBuilder.getMethod ("create", null); create.invoke (httpBuilder, null); } catch (uitzondering e) {e.printStackTrace (); }}

Laten we nu de Gradle-taak opnieuw uitvoeren:

$ ./gradlew lintGradle> Taak: lintGradle FAILED # foutuitvoer weggelaten waarschuwing ongebruikte-afhankelijkheid een of meer klassen in org.apache. httpcomponents: httpcore: 4.4.13 zijn direct vereist door uw code (geen auto-fix beschikbaar) waarschuwing ongebruikt- afhankelijkheid deze afhankelijkheid is ongebruikt en kan worden verwijderd ongebruikte-afhankelijkheden / build.gradle: 9 implementatie ('org.apache.httpcomponents: httpclient: 4.5.12') ✖ 2 problemen (0 fouten, 2 waarschuwingen) 

Wat is er gebeurd? We gebruikten HttpClientBuilder van onze afhankelijkheid (httpclient) maar kreeg nog steeds fouten.

Als we een bibliotheek met reflectie gebruiken, detecteert de plug-in het gebruik ervan niet.

Als gevolg hiervan kunnen we dezelfde twee fouten zien.

Over het algemeen moeten we dergelijke afhankelijkheden configureren als looptijdAlleen.

3.4. Rapporten genereren

Voor grote projecten wordt het aantal fouten dat in een terminal wordt geretourneerd, een uitdaging om af te handelen.

Laten we de plug-in configureren om ons in plaats daarvan een rapport te geven:

allprojects {pas plug-in toe: "java" pas plug-in toe: "nebula.lint" gradleLint {rules = ['unused-dependency'] reportFormat = 'text'} // andere details weggelaten}

Laten we voer de ... uit genererenGradleLintReport taak en bekijk onze build output:

$ ./gradlew genererenGradleLintReport # taakuitvoer weggelaten $ cat unused-dependencies / build / reports / gradleLint / unused-dependencies.txt Rapport CodeNarc - 20 juni 2020, 15:25:28 Samenvatting: TotalFiles = 1 FilesWithViolations = 1 P1 = 0 P2 = 3 P3 = 0 Bestand: /home/user/tutorials/gradle-5/unused-dependencies/build.gradle Overtreding: Regel = ongebruikte-afhankelijkheid P = 2 Regel = null Msg = [een of meer klassen in org. apache.httpcomponents: httpcore: 4.4.13 zijn direct vereist door uw code] Overtreding: Regel = ongebruikte-afhankelijkheid P = 2 Regel = 9 Msg = [deze afhankelijkheid is ongebruikt en kan worden verwijderd] Src = [implementatie ('org.apache .httpcomponents: httpclient: 4.5.12 ')] Schending: Rule = unused-dependency P = 2 Line = 17 Msg = [deze afhankelijkheid is ongebruikt en kan worden verwijderd] Src = [testImplementation (' junit: junit: 4.12 ')] [CodeNarc (//www.codenarc.org) v0.25.2] 

Nu detecteert het ongebruikte afhankelijkheden op het testCompileClasspath configuratie.

Dit is helaas een inconsistent gedrag van de plug-in. Als resultaat krijgen we nu drie foutmeldingen.

4. Conclusie

In deze zelfstudie hebben we gezien hoe we ongebruikte afhankelijkheden van Gradle-builds kunnen vinden.

Eerst hebben we de algemene opzet uitgelegd. Daarna hebben we de gerapporteerde fouten onderzocht met verschillende afhankelijkheden en hun gebruik.

Ten slotte hebben we gezien hoe we op tekst gebaseerde rapporten kunnen genereren.

Zoals gewoonlijk kunnen we de volledige codevoorbeelden vinden op GitHub.