Skip to content

Commit

Permalink
Make gradle dependency configuration errors into its own data table.
Browse files Browse the repository at this point in the history
  • Loading branch information
sambsnyd committed Nov 8, 2023
1 parent 3f57f69 commit 9df8e43
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
import org.openrewrite.groovy.GroovyIsoVisitor;
import org.openrewrite.groovy.tree.G;
import org.openrewrite.internal.lang.Nullable;
import org.openrewrite.java.dependencies.table.GradleDependencyConfigurationErrors;
import org.openrewrite.java.dependencies.table.RepositoryAccessibilityReport;
import org.openrewrite.marker.SearchResult;
import org.openrewrite.maven.internal.MavenPomDownloader;
import org.openrewrite.maven.tree.MavenRepository;
import org.openrewrite.maven.tree.MavenResolutionResult;
Expand All @@ -40,6 +40,7 @@
public class DependencyResolutionDiagnostic extends ScanningRecipe<DependencyResolutionDiagnostic.Accumulator> {

transient RepositoryAccessibilityReport report = new RepositoryAccessibilityReport(this);
transient GradleDependencyConfigurationErrors gradleErrors = new GradleDependencyConfigurationErrors(this);

@Override
public String getDisplayName() {
Expand All @@ -48,9 +49,15 @@ public String getDisplayName() {

@Override
public String getDescription() {
return "Recipes which manipulate dependencies must be able to successfully access the repositories used by the " +
"project and retrieve dependency metadata from them. This recipe lists the repositories that were found " +
"and whether or not dependency metadata could successfully be resolved from them.";
return "Recipes which manipulate dependencies must be able to successfully access the artifact repositories " +
"and resolve dependencies from them. This recipe produces two data tables used to understand the state " +
"of dependency resolution.\n\n" +
"The Repository accessibility report lists all the artifact repositories known to the project and whether" +
"they respond to network access. The network access is attempted while the recipe is run and so is " +
"representative of current conditions.\n\n" +
"The Gradle dependency configuration errors lists all the dependency configurations that failed to " +
"resolve one or more dependencies when the project was parsed. This is representative of conditions at " +
"the time the LST was parsed.";
}

public static class Accumulator {
Expand Down Expand Up @@ -168,11 +175,7 @@ public G.CompilationUnit visitCompilationUnit(G.CompilationUnit cu, ExecutionCon
if (conf.getExceptionType() == null) {
continue;
}
g = SearchResult.found(g, "Found Gradle dependency configuration which failed to resolve during parsing: " +
conf.getName() + ": " + conf.getExceptionType() + " - " + conf.getMessage());
// If one configuration failed to resolve, others likely failed and probably for the same reasons
// Record only first failure to reduce noise
break;
gradleErrors.insertRow(ctx, new GradleDependencyConfigurationErrors.Row(gp.getPath(), conf.getName(), conf.getExceptionType(), conf.getMessage()));
}

return g;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.openrewrite.java.dependencies.table;

import lombok.Value;
import org.openrewrite.Column;
import org.openrewrite.DataTable;
import org.openrewrite.Recipe;

public class GradleDependencyConfigurationErrors extends DataTable<GradleDependencyConfigurationErrors.Row> {


public GradleDependencyConfigurationErrors(Recipe recipe) {
super(recipe, "Gradle dependency configuration errors",
"Records Gradle dependency configurations which failed to resolve during parsing. " +
"Partial success/failure is common, a failure in this list does not mean that every dependency failed to resolve.");
}

@Value
public static class Row {
@Column(displayName = "Project path",
description = "The path of the project which contains the dependency configuration.")
String projectPath;

@Column(displayName = "Configuration name",
description = "The name of the dependency configuration which failed to resolve.")
String configurationName;

@Column(displayName = "Exception type",
description = "The type of exception encountered when attempting to resolve the dependency configuration.")
String exceptionType;

@Column(displayName = "Error message",
description = "The error message encountered when attempting to resolve the dependency configuration.")
String exceptionMessage;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public void defaults(RecipeSpec spec) {
void gradle() {
rewriteRun(
spec -> spec.beforeRecipe(withToolingApi())
// It is a limitation of the tooling API which prevents configuration-granularity error information from being collected.
// So the GradleDependencyConfigurationErrors table will never be populated in unit tests.
.dataTable(RepositoryAccessibilityReport.Row.class, rows -> {
assertThat(rows).hasSize(4);
assertThat(rows).contains(
Expand All @@ -63,26 +65,7 @@ void gradle() {
dependencies {
implementation("org.openrewrite.nonexistent:nonexistent:0.0.0")
}
"""
// It is a limitation of the tooling API which prevents configuration-granularity error information from being collected.
// When run with real Gradle this recipe _should_ produce the following result, included here for documentation.
// ,"""
// ~~(Found Gradle dependency configuration which failed to resolve during parsing)~~>plugins {
// id("java")
// }
// repositories {
// mavenLocal()
// mavenCentral()
// maven {
// url "https://nonexistent.moderne.io/maven2"
// }
// }
//
// dependencies {
// implementation("org.openrewrite.nonexistent:nonexistent:0.0.0")
// }
// """
)
""")
);
}

Expand Down

0 comments on commit 9df8e43

Please sign in to comment.