Skip to content

Commit 968a22f

Browse files
authored
Gate Kotlin-based Java version cap on actual Kotlin sources (#1066)
1 parent a471dd1 commit 968a22f

4 files changed

Lines changed: 177 additions & 7 deletions

File tree

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* Copyright 2026 the original author or authors.
3+
* <p>
4+
* Licensed under the Moderne Source Available License (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* https://docs.moderne.io/licensing/moderne-source-available-license
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.openrewrite.java.migrate.search;
17+
18+
import lombok.EqualsAndHashCode;
19+
import lombok.Value;
20+
import org.jspecify.annotations.Nullable;
21+
import org.openrewrite.ExecutionContext;
22+
import org.openrewrite.Option;
23+
import org.openrewrite.ScanningRecipe;
24+
import org.openrewrite.SourceFile;
25+
import org.openrewrite.Tree;
26+
import org.openrewrite.TreeVisitor;
27+
import org.openrewrite.java.marker.JavaProject;
28+
import org.openrewrite.marker.SearchResult;
29+
30+
import java.util.HashSet;
31+
import java.util.Optional;
32+
import java.util.Set;
33+
34+
@EqualsAndHashCode(callSuper = false)
35+
@Value
36+
public class ModuleHasKotlinSource extends ScanningRecipe<Set<JavaProject>> {
37+
38+
@Option(displayName = "Invert marking",
39+
description = "If `true`, marks files in modules that do *not* contain Kotlin sources. Defaults to `false`.",
40+
required = false)
41+
@Nullable
42+
Boolean invertMarking;
43+
44+
@Override
45+
public String getDisplayName() {
46+
return "Module has Kotlin source files";
47+
}
48+
49+
@Override
50+
public String getDescription() {
51+
return "Marks all files in modules that contain at least one Kotlin source file (`.kt`). " +
52+
"Intended as a precondition to scope recipes to projects that actually compile Kotlin, " +
53+
"as opposed to projects that merely pick up `kotlin-stdlib` transitively.";
54+
}
55+
56+
@Override
57+
public Set<JavaProject> getInitialValue(ExecutionContext ctx) {
58+
return new HashSet<>();
59+
}
60+
61+
@Override
62+
public TreeVisitor<?, ExecutionContext> getScanner(Set<JavaProject> acc) {
63+
return new TreeVisitor<Tree, ExecutionContext>() {
64+
@Override
65+
public Tree visit(@Nullable Tree tree, ExecutionContext ctx) {
66+
if (tree instanceof SourceFile) {
67+
SourceFile sourceFile = (SourceFile) tree;
68+
if (sourceFile.getSourcePath().toString().endsWith(".kt")) {
69+
sourceFile.getMarkers().findFirst(JavaProject.class).ifPresent(acc::add);
70+
}
71+
}
72+
return tree;
73+
}
74+
};
75+
}
76+
77+
@Override
78+
public TreeVisitor<?, ExecutionContext> getVisitor(Set<JavaProject> acc) {
79+
return new TreeVisitor<Tree, ExecutionContext>() {
80+
@Override
81+
public Tree visit(@Nullable Tree tree, ExecutionContext ctx) {
82+
assert tree != null;
83+
boolean shouldInvert = Boolean.TRUE.equals(invertMarking);
84+
Optional<JavaProject> maybeJp = tree.getMarkers().findFirst(JavaProject.class);
85+
if (!maybeJp.isPresent()) {
86+
if (shouldInvert) {
87+
return SearchResult.found(tree, "No module, so vacuously has no Kotlin source");
88+
}
89+
return tree;
90+
}
91+
JavaProject jp = maybeJp.get();
92+
if (shouldInvert && !acc.contains(jp)) {
93+
return SearchResult.found(tree, "Module does not have Kotlin source");
94+
}
95+
if (!shouldInvert && acc.contains(jp)) {
96+
return SearchResult.found(tree, "Module has Kotlin source");
97+
}
98+
return tree;
99+
}
100+
};
101+
}
102+
}

src/main/resources/META-INF/rewrite/java-version-25.yml

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ recipeList:
3030
- org.openrewrite.java.migrate.UpgradeToJava21
3131
- org.openrewrite.java.migrate.UpgradeBuildToJava24
3232
- org.openrewrite.java.migrate.UpgradeBuildToJava25
33+
- org.openrewrite.java.migrate.UpgradeBuildToJava25ForKotlin
3334
- org.openrewrite.java.migrate.UpgradePluginsForJava25
3435
- org.openrewrite.java.migrate.io.ReplaceSystemOutWithIOPrint
3536
- org.openrewrite.java.migrate.lang.MigrateMainMethodToInstanceMain
@@ -248,8 +249,10 @@ type: specs.openrewrite.org/v1beta/recipe
248249
name: org.openrewrite.java.migrate.UpgradeBuildToJava24
249250
displayName: Upgrade build to Java 24 for Kotlin pre-2.3
250251
description: >-
251-
Kotlin versions before 2.3 only support up to Java 24.
252+
Kotlin versions before 2.3 only support up to Java 24. Applies only to modules that actually compile Kotlin
253+
(i.e. contain `.kt` source files), so transitive `kotlin-stdlib` dependencies do not trigger the cap.
252254
preconditions:
255+
- org.openrewrite.java.migrate.search.ModuleHasKotlinSource
253256
- org.openrewrite.java.dependencies.search.ModuleHasDependency:
254257
groupIdPattern: org.jetbrains.kotlin
255258
artifactIdPattern: kotlin-stdlib*
@@ -261,10 +264,25 @@ recipeList:
261264
---
262265
type: specs.openrewrite.org/v1beta/recipe
263266
name: org.openrewrite.java.migrate.UpgradeBuildToJava25
264-
displayName: Upgrade build to Java 25 (default)
267+
displayName: Upgrade build to Java 25 (non-Kotlin)
265268
description: >-
266-
Upgrades build files to Java 25 for projects without Kotlin pre-2.3.
269+
Upgrades build files to Java 25 for modules without Kotlin source files. This covers pure Java projects,
270+
including those that only pick up `kotlin-stdlib` transitively through another dependency.
267271
preconditions:
272+
- org.openrewrite.java.migrate.search.ModuleHasKotlinSource:
273+
invertMarking: true
274+
recipeList:
275+
- org.openrewrite.java.migrate.UpgradeJavaVersion:
276+
version: 25
277+
278+
---
279+
type: specs.openrewrite.org/v1beta/recipe
280+
name: org.openrewrite.java.migrate.UpgradeBuildToJava25ForKotlin
281+
displayName: Upgrade build to Java 25 for Kotlin 2.3+
282+
description: >-
283+
Upgrades build files to Java 25 for Kotlin modules already on Kotlin 2.3 or later.
284+
preconditions:
285+
- org.openrewrite.java.migrate.search.ModuleHasKotlinSource
268286
- org.openrewrite.java.dependencies.search.ModuleHasDependency:
269287
groupIdPattern: org.jetbrains.kotlin
270288
artifactIdPattern: kotlin-stdlib*

0 commit comments

Comments
 (0)