3030import org .openrewrite .java .search .UsesType ;
3131import org .openrewrite .java .tree .J ;
3232import org .openrewrite .java .tree .JavaSourceFile ;
33+ import org .openrewrite .marker .Markup ;
34+ import org .openrewrite .maven .MavenDownloadingException ;
35+ import org .openrewrite .maven .MavenExecutionContextView ;
36+ import org .openrewrite .maven .internal .MavenPomDownloader ;
3337import org .openrewrite .maven .table .MavenMetadataFailures ;
34- import org .openrewrite .maven .tree .GroupArtifact ;
38+ import org .openrewrite .maven .tree .*;
39+ import org .openrewrite .maven .utilities .JavaSourceSetUpdater ;
3540import org .openrewrite .semver .Semver ;
41+ import org .openrewrite .semver .VersionComparator ;
3642
3743import java .util .*;
3844
@@ -138,6 +144,11 @@ public Validated<Object> validate() {
138144 public static class Scanned {
139145 Map <JavaProject , Boolean > usingType = new HashMap <>();
140146 Map <JavaProject , Set <String >> configurationsByProject = new HashMap <>();
147+ @ Nullable
148+ String resolvedVersion ;
149+ List <MavenRepository > repositories = new ArrayList <>();
150+ @ Nullable
151+ Exception versionResolutionFailure ;
141152 }
142153
143154 @ Override
@@ -176,7 +187,9 @@ private boolean usesType(SourceFile sourceFile, ExecutionContext ctx) {
176187 sourceFile == hasTestSourceSet .visit (sourceFile , ctx )) {
177188 return tree ;
178189 }
179- sourceFile .getMarkers ().findFirst (JavaProject .class ).ifPresent (javaProject -> {
190+ Optional <JavaProject > maybeJavaProject = sourceFile .getMarkers ().findFirst (JavaProject .class );
191+ if (maybeJavaProject .isPresent ()) {
192+ JavaProject javaProject = maybeJavaProject .get ();
180193 boolean uses = usesType (sourceFile , ctx );
181194 acc .usingType .compute (javaProject , (jp , usingType ) -> Boolean .TRUE .equals (usingType ) || uses );
182195
@@ -185,7 +198,25 @@ private boolean usesType(SourceFile sourceFile, ExecutionContext ctx) {
185198 sourceFile .getMarkers ().findFirst (JavaSourceSet .class ).ifPresent (sourceSet ->
186199 configurations .add ("main" .equals (sourceSet .getName ()) ? "implementation" : sourceSet .getName () + "Implementation" ));
187200 }
188- });
201+
202+ // Resolve version once for JavaSourceSet updates
203+ if (acc .resolvedVersion == null && version != null ) {
204+ Optional <GradleProject > maybeGp = sourceFile .getMarkers ().findFirst (GradleProject .class );
205+ if (maybeGp .isPresent ()) {
206+ try {
207+ DependencyVersionSelector selector = new DependencyVersionSelector (metadataFailures , maybeGp .get (), null );
208+ acc .resolvedVersion = selector .select (
209+ new GroupArtifact (groupId , artifactId ), "implementation" ,
210+ version , versionPattern , ctx );
211+ if (acc .resolvedVersion != null ) {
212+ acc .repositories = maybeGp .get ().getMavenRepositories ();
213+ }
214+ } catch (MavenDownloadingException e ) {
215+ acc .versionResolutionFailure = e ;
216+ }
217+ }
218+ }
219+ }
189220 return tree ;
190221 }
191222 };
@@ -196,7 +227,7 @@ public TreeVisitor<?, ExecutionContext> getVisitor(Scanned acc) {
196227 // Allow when configuration is explicitly provided, when onlyIfUsing is not set (default to "implementation"),
197228 // or when source files were scanned
198229 boolean hasExplicitConfiguration = !StringUtils .isBlank (configuration );
199- return Preconditions .check (hasExplicitConfiguration || onlyIfUsing == null || !acc .configurationsByProject .isEmpty (),
230+ TreeVisitor <?, ExecutionContext > gradleVisitor = Preconditions .check (hasExplicitConfiguration || onlyIfUsing == null || !acc .configurationsByProject .isEmpty (),
200231 Preconditions .check (new IsBuildGradle <>(true ), new JavaIsoVisitor <ExecutionContext >() {
201232
202233 @ Override
@@ -280,5 +311,65 @@ private boolean isTopLevel(Cursor cursor) {
280311 }
281312 })
282313 );
314+
315+ if (acc .configurationsByProject .isEmpty () || acc .resolvedVersion == null ) {
316+ if (acc .versionResolutionFailure != null ) {
317+ Exception failure = acc .versionResolutionFailure ;
318+ return new TreeVisitor <Tree , ExecutionContext >() {
319+ @ Override
320+ public boolean isAcceptable (SourceFile sourceFile , ExecutionContext ctx ) {
321+ return gradleVisitor .isAcceptable (sourceFile , ctx );
322+ }
323+
324+ @ Override
325+ public @ Nullable Tree visit (@ Nullable Tree tree , ExecutionContext ctx ) {
326+ Tree result = gradleVisitor .visit (tree , ctx );
327+ if (result != tree ) {
328+ result = Markup .warn (result , failure );
329+ }
330+ return result ;
331+ }
332+ };
333+ }
334+ return gradleVisitor ;
335+ }
336+
337+ return new TreeVisitor <Tree , ExecutionContext >() {
338+ @ Nullable
339+ private JavaSourceSetUpdater updater ;
340+
341+ @ Override
342+ public boolean isAcceptable (SourceFile sourceFile , ExecutionContext ctx ) {
343+ return gradleVisitor .isAcceptable (sourceFile , ctx ) || sourceFile instanceof JavaSourceFile ;
344+ }
345+
346+ @ Override
347+ public @ Nullable Tree visit (@ Nullable Tree tree , ExecutionContext ctx ) {
348+ if (!(tree instanceof SourceFile )) {
349+ return tree ;
350+ }
351+ SourceFile sf = (SourceFile ) tree ;
352+ if (gradleVisitor .isAcceptable (sf , ctx )) {
353+ return gradleVisitor .visit (tree , ctx );
354+ }
355+ if (sf instanceof JavaSourceFile ) {
356+ return updateJavaSourceSet (sf , ctx );
357+ }
358+ return tree ;
359+ }
360+
361+ private SourceFile updateJavaSourceSet (SourceFile sf , ExecutionContext ctx ) {
362+ Optional <JavaProject > maybeJp = sf .getMarkers ().findFirst (JavaProject .class );
363+ if (!maybeJp .isPresent () || !acc .configurationsByProject .containsKey (maybeJp .get ())) {
364+ return sf ;
365+ }
366+ if (updater == null ) {
367+ updater = new JavaSourceSetUpdater (ctx );
368+ }
369+ return JavaSourceSet .updateOnSourceFile (sf , sourceSet ->
370+ sourceSet .getGavToTypes ().isEmpty () ? sourceSet :
371+ updater .addDependency (sourceSet , groupId , artifactId , acc .resolvedVersion , acc .repositories ));
372+ }
373+ };
283374 }
284375}
0 commit comments