Skip to content

Commit 7ac8fb8

Browse files
authored
Merge branch 'main' into timtebeek/gradle-kts-templates
2 parents 11bdbd5 + d4392fc commit 7ac8fb8

26 files changed

Lines changed: 1428 additions & 148 deletions

File tree

rewrite-core/src/main/java/org/openrewrite/marketplace/RecipeListing.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@
2626
import java.time.Duration;
2727
import java.util.*;
2828

29-
import static java.util.Collections.singleton;
30-
3129
@Getter
3230
@RequiredArgsConstructor
3331
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@@ -92,10 +90,9 @@ public int compareTo(RecipeListing o) {
9290

9391
public static RecipeListing fromDescriptor(RecipeDescriptor descriptor, RecipeBundle bundle) {
9492
int recipeCount = 1;
95-
RecipeDescriptor d = descriptor;
96-
for (Queue<RecipeDescriptor> queue = new LinkedList<>(singleton(descriptor)); !queue.isEmpty();
97-
d = queue.poll()) {
98-
recipeCount += d.getRecipeList().size();
93+
for (Queue<RecipeDescriptor> queue = new LinkedList<>(descriptor.getRecipeList()); !queue.isEmpty(); ) {
94+
RecipeDescriptor d = queue.poll();
95+
recipeCount++;
9996
queue.addAll(d.getRecipeList());
10097
}
10198

rewrite-gradle/src/main/java/org/openrewrite/gradle/plugins/UpgradePluginVersion.java

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,15 +133,30 @@ public TreeVisitor<?, ExecutionContext> getScanner(DependencyVersionState acc) {
133133
@Nullable
134134
private GradleSettings gradleSettings;
135135

136+
private final Map<String, String> localVariableValues = new HashMap<>();
137+
136138
@Override
137139
public @Nullable J visit(@Nullable Tree tree, ExecutionContext ctx) {
138140
if (tree instanceof SourceFile) {
139141
gradleProject = tree.getMarkers().findFirst(GradleProject.class).orElse(null);
140142
gradleSettings = tree.getMarkers().findFirst(GradleSettings.class).orElse(null);
143+
localVariableValues.clear();
141144
}
142145
return super.visit(tree, ctx);
143146
}
144147

148+
@Override
149+
public J visitVariable(J.VariableDeclarations.NamedVariable variable, ExecutionContext ctx) {
150+
J.VariableDeclarations.NamedVariable v = (J.VariableDeclarations.NamedVariable) super.visitVariable(variable, ctx);
151+
if (v.getInitializer() instanceof J.Literal) {
152+
String value = literalValue(v.getInitializer());
153+
if (value != null) {
154+
localVariableValues.put(v.getSimpleName(), value);
155+
}
156+
}
157+
return v;
158+
}
159+
145160
@Override
146161
public J visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) {
147162
J.MethodInvocation m = (J.MethodInvocation) super.visitMethodInvocation(method, ctx);
@@ -185,20 +200,34 @@ public J visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx)
185200

186201
G.GString.Value gStringValue = (G.GString.Value) gString.getStrings().get(0);
187202
String versionVariableName = gStringValue.getTree().toString();
203+
String resolverPluginId = pluginId;
204+
if ("kotlin".equals(pluginId)) {
205+
resolverPluginId = String.format("org.jetbrains.%s.%s", pluginId, literalValue(pluginArgs.get(0)));
206+
}
188207
String resolvedPluginVersion = new DependencyVersionSelector(metadataFailures, gradleProject, gradleSettings)
189-
.select(new GroupArtifact(pluginId, pluginId + ".gradle.plugin"), "classpath", newVersion, versionPattern, ctx);
208+
.select(new GroupArtifact(resolverPluginId, resolverPluginId + ".gradle.plugin"), "classpath", newVersion, versionPattern, ctx);
190209

191210
acc.versionPropNameToPluginId.put(versionVariableName, pluginId);
192211
assert resolvedPluginVersion != null;
193212
acc.pluginIdToNewVersion.put(pluginId, resolvedPluginVersion);
194213
} else if (versionArgs.get(0) instanceof J.Identifier) {
195214
J.Identifier identifier = (J.Identifier) versionArgs.get(0);
196215
String versionVariableName = identifier.getSimpleName();
197-
String resolvedPluginVersion = new DependencyVersionSelector(metadataFailures, gradleProject, gradleSettings)
198-
.select(new GroupArtifact(pluginId, pluginId + ".gradle.plugin"), "classpath", newVersion, versionPattern, ctx);
216+
String resolverPluginId = pluginId;
217+
if ("kotlin".equals(pluginId)) {
218+
resolverPluginId = String.format("org.jetbrains.%s.%s", pluginId, literalValue(pluginArgs.get(0)));
219+
}
220+
String localCurrentVersion = localVariableValues.get(versionVariableName);
221+
String resolvedPluginVersion;
222+
if (localCurrentVersion != null) {
223+
resolvedPluginVersion = new DependencyVersionSelector(metadataFailures, gradleProject, gradleSettings)
224+
.select(new GroupArtifactVersion(resolverPluginId, resolverPluginId + ".gradle.plugin", localCurrentVersion), "classpath", newVersion, versionPattern, ctx);
225+
} else {
226+
resolvedPluginVersion = new DependencyVersionSelector(metadataFailures, gradleProject, gradleSettings)
227+
.select(new GroupArtifact(resolverPluginId, resolverPluginId + ".gradle.plugin"), "classpath", newVersion, versionPattern, ctx);
228+
}
199229

200230
acc.versionPropNameToPluginId.put(versionVariableName, pluginId);
201-
assert resolvedPluginVersion != null;
202231
acc.pluginIdToNewVersion.put(pluginId, resolvedPluginVersion);
203232
}
204233
} catch (MavenDownloadingException e) {

rewrite-gradle/src/test/java/org/openrewrite/gradle/plugins/UpgradePluginVersionTest.java

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,66 @@ void upgradeKotlinPlugin() {
9898
);
9999
}
100100

101+
@Test
102+
void upgradeKotlinPluginLocalVariable() {
103+
rewriteRun(
104+
spec -> spec.recipe(new UpgradePluginVersion("kotlin", "2.1.0", null)),
105+
buildGradleKts(
106+
"""
107+
plugins {
108+
val kotlinVersion = "1.9.25"
109+
kotlin("jvm") version kotlinVersion
110+
kotlin("plugin.allopen") version kotlinVersion
111+
kotlin("plugin.spring") version kotlinVersion
112+
}
113+
""",
114+
"""
115+
plugins {
116+
val kotlinVersion = "2.1.0"
117+
kotlin("jvm") version kotlinVersion
118+
kotlin("plugin.allopen") version kotlinVersion
119+
kotlin("plugin.spring") version kotlinVersion
120+
}
121+
"""
122+
)
123+
);
124+
}
125+
126+
@Test
127+
void upgradeKotlinPluginLocalVariableWithSemverSelector() {
128+
rewriteRun(
129+
spec -> spec.recipe(new UpgradePluginVersion("kotlin", "latest.minor", null)),
130+
buildGradleKts(
131+
"""
132+
plugins {
133+
val kotlinVersion = "2.0.0"
134+
kotlin("jvm") version kotlinVersion
135+
}
136+
""",
137+
spec -> spec.after(s -> {
138+
assertThat(s).doesNotContain("2.0.0");
139+
assertThat(s).containsPattern("val kotlinVersion = \"2.\\d+.\\d+\"");
140+
return s;
141+
})
142+
)
143+
);
144+
}
145+
146+
@Test
147+
void dontDowngradeKotlinPluginLocalVariable() {
148+
rewriteRun(
149+
spec -> spec.recipe(new UpgradePluginVersion("kotlin", "1.9.0", null)),
150+
buildGradleKts(
151+
"""
152+
plugins {
153+
val kotlinVersion = "1.9.25"
154+
kotlin("jvm") version kotlinVersion
155+
}
156+
"""
157+
)
158+
);
159+
}
160+
101161
@Test
102162
void upgradeGradleSettingsPlugin() {
103163
rewriteRun(

rewrite-maven/src/test/java/org/openrewrite/maven/ChangeDependencyGroupIdAndArtifactIdTest.java

Lines changed: 13 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.openrewrite.test.RewriteTest;
2323
import org.openrewrite.test.SourceSpec;
2424

25+
import static org.assertj.core.api.Assertions.assertThat;
2526
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
2627
import static org.openrewrite.java.Assertions.mavenProject;
2728
import static org.openrewrite.maven.Assertions.pomXml;
@@ -3329,33 +3330,10 @@ void versionNotDroppedWhenDependencyExcludedByOtherDependency() {
33293330
</dependencies>
33303331
</project>
33313332
""",
3332-
"""
3333-
<project>
3334-
<modelVersion>4.0.0</modelVersion>
3335-
<groupId>com.mycompany.app</groupId>
3336-
<artifactId>my-app</artifactId>
3337-
<version>1</version>
3338-
<dependencies>
3339-
<dependency>
3340-
<groupId>io.swagger.core.v3</groupId>
3341-
<artifactId>swagger-jaxrs2</artifactId>
3342-
<version>2.2.20</version>
3343-
<scope>provided</scope>
3344-
<exclusions>
3345-
<exclusion>
3346-
<groupId>com.fasterxml.jackson.jaxrs</groupId>
3347-
<artifactId>*</artifactId>
3348-
</exclusion>
3349-
</exclusions>
3350-
</dependency>
3351-
<dependency>
3352-
<groupId>com.fasterxml.jackson.jakarta.rs</groupId>
3353-
<artifactId>jackson-jakarta-rs-json-provider</artifactId>
3354-
<version>2.21.0</version>
3355-
</dependency>
3356-
</dependencies>
3357-
</project>
3358-
"""
3333+
spec -> spec.after(actual -> assertThat(actual)
3334+
.containsPattern("<groupId>com\\.fasterxml\\.jackson\\.jakarta\\.rs</groupId>\\s*<artifactId>jackson-jakarta-rs-json-provider</artifactId>\\s*<version>2\\.\\d+\\.\\d+</version>")
3335+
.doesNotContain("<version>2.9.7</version>")
3336+
.actual())
33593337
)
33603338
);
33613339
}
@@ -3405,33 +3383,10 @@ void versionNotDroppedWhenTransitiveDependencyHasManagedVersion() {
34053383
</dependencies>
34063384
</project>
34073385
""",
3408-
"""
3409-
<project>
3410-
<modelVersion>4.0.0</modelVersion>
3411-
<groupId>com.mycompany.app</groupId>
3412-
<artifactId>my-app</artifactId>
3413-
<version>1</version>
3414-
<dependencies>
3415-
<dependency>
3416-
<groupId>io.swagger.core.v3</groupId>
3417-
<artifactId>swagger-jaxrs2-jakarta</artifactId>
3418-
<version>2.2.20</version>
3419-
<scope>provided</scope>
3420-
<exclusions>
3421-
<exclusion>
3422-
<groupId>com.fasterxml.jackson.jaxrs</groupId>
3423-
<artifactId>*</artifactId>
3424-
</exclusion>
3425-
</exclusions>
3426-
</dependency>
3427-
<dependency>
3428-
<groupId>com.fasterxml.jackson.jakarta.rs</groupId>
3429-
<artifactId>jackson-jakarta-rs-json-provider</artifactId>
3430-
<version>2.21.0</version>
3431-
</dependency>
3432-
</dependencies>
3433-
</project>
3434-
"""
3386+
spec -> spec.after(actual -> assertThat(actual)
3387+
.containsPattern("<groupId>com\\.fasterxml\\.jackson\\.jakarta\\.rs</groupId>\\s*<artifactId>jackson-jakarta-rs-json-provider</artifactId>\\s*<version>2\\.\\d+\\.\\d+</version>")
3388+
.doesNotContain("<version>2.9.7</version>")
3389+
.actual())
34353390
)
34363391
);
34373392
}
@@ -3574,33 +3529,10 @@ void exclusionUpdatedWhenDependencyGroupIdChanges() {
35743529
</dependencies>
35753530
</project>
35763531
""",
3577-
"""
3578-
<project>
3579-
<modelVersion>4.0.0</modelVersion>
3580-
<groupId>com.mycompany.app</groupId>
3581-
<artifactId>my-app</artifactId>
3582-
<version>1</version>
3583-
<dependencies>
3584-
<dependency>
3585-
<groupId>io.swagger.core.v3</groupId>
3586-
<artifactId>swagger-jaxrs2-jakarta</artifactId>
3587-
<version>2.2.20</version>
3588-
<scope>provided</scope>
3589-
<exclusions>
3590-
<exclusion>
3591-
<groupId>com.fasterxml.jackson.jakarta.rs</groupId>
3592-
<artifactId>jackson-jakarta-rs-json-provider</artifactId>
3593-
</exclusion>
3594-
</exclusions>
3595-
</dependency>
3596-
<dependency>
3597-
<groupId>com.fasterxml.jackson.jakarta.rs</groupId>
3598-
<artifactId>jackson-jakarta-rs-json-provider</artifactId>
3599-
<version>2.21.0</version>
3600-
</dependency>
3601-
</dependencies>
3602-
</project>
3603-
"""
3532+
spec -> spec.after(actual -> assertThat(actual)
3533+
.containsPattern("<groupId>com\\.fasterxml\\.jackson\\.jakarta\\.rs</groupId>\\s*<artifactId>jackson-jakarta-rs-json-provider</artifactId>\\s*<version>2\\.\\d+\\.\\d+</version>")
3534+
.doesNotContain("<version>2.9.7</version>")
3535+
.actual())
36043536
)
36053537
);
36063538
}

rewrite-python/rewrite/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ requires-python = ">=3.10"
2424
dependencies = [
2525
"cbor2>=5.6.5",
2626
"more_itertools>=10.0.0",
27-
"ty-types>=0.0.18.dev0", # Type inference CLI for Python type attribution
27+
"ty-types>=0.0.19.dev20260223122104", # Type inference CLI for Python type attribution
2828
"parso>=0.7.1,<0.8", # Python 2/3 parser with CST support (0.8+ dropped Python 2.7 grammar)
2929
]
3030

rewrite-python/rewrite/src/rewrite/python/_parser_visitor.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,8 @@ def visit_arguments(self, node, with_close_paren: bool = True) -> List[JRightPad
338338
def map_arg(self, node, default=None, vararg=False, kwarg=False):
339339
prefix = self.__source_before('**') if kwarg else self.__whitespace()
340340
vararg_prefix = self.__source_before('*') if vararg else None
341-
name = self.__convert_name(node.arg, self._type_mapping.type(node))
341+
expr_type, field_type = self._type_mapping.param_type_info(node)
342+
name = self.__convert_name(node.arg, expr_type, field_type)
342343
after_name = self.__source_before(':') if node.annotation else Space.EMPTY
343344
type_expression = self.__convert_type(node.annotation) if node.annotation else None
344345
initializer = self.__pad_left(self.__source_before('='), self.__convert(default)) if default else None
@@ -359,7 +360,7 @@ def map_arg(self, node, default=None, vararg=False, kwarg=False):
359360
cast(j.Identifier, name),
360361
[],
361362
initializer,
362-
self.__as_variable_type(self._type_mapping.type(node))
363+
field_type
363364
), after_name)],
364365
)
365366

@@ -2182,7 +2183,7 @@ def visit_FunctionDef(self, node: ast.FunctionDef) -> j.MethodDeclaration:
21822183
None,
21832184
body,
21842185
None,
2185-
self.__as_method_type(self._type_mapping.type(node)),
2186+
self._type_mapping.method_declaration_type(node),
21862187
)
21872188

21882189
def __map_decorator(self, decorator) -> j.Annotation:
@@ -2871,7 +2872,7 @@ def __convert_type_mapper(self, node) -> Optional[TypeTree]:
28712872
enumerate(slices)],
28722873
Markers.EMPTY
28732874
),
2874-
None
2875+
self._type_mapping.type(node)
28752876
)
28762877
elif isinstance(node, ast.BinOp):
28772878
# Type unions using `|` was added in Python 3.10
@@ -3039,12 +3040,13 @@ def __as_method_type(t: Optional[JavaType]) -> Optional[JavaType]:
30393040
return t
30403041
return None
30413042

3042-
def __convert_name(self, name: str, name_type: Optional[JavaType] = None) -> NameTree:
3043+
def __convert_name(self, name: str, name_type: Optional[JavaType] = None,
3044+
field_type: Optional[JavaType.Variable] = None) -> NameTree:
30433045
def ident_or_field(parts: List[str]) -> NameTree:
30443046
if len(parts) == 1:
30453047
space, actual_name = self.__consume_identifier(parts[-1])
30463048
return j.Identifier(random_id(), space, Markers.EMPTY, [], actual_name,
3047-
name_type, None)
3049+
name_type, field_type)
30483050
else:
30493051
return j.FieldAccess(
30503052
random_id(),
@@ -3055,7 +3057,7 @@ def ident_or_field(parts: List[str]) -> NameTree:
30553057
self.__source_before('.'),
30563058
(lambda s, n: j.Identifier(random_id(), s, Markers.EMPTY, [], n,
30573059
name_type,
3058-
None))(*self.__consume_identifier(parts[-1])),
3060+
field_type))(*self.__consume_identifier(parts[-1])),
30593061
),
30603062
name_type
30613063
)

rewrite-python/rewrite/src/rewrite/python/remove_import.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
from rewrite.java import J
2222
from rewrite.java.support_types import JContainer, JRightPadded
23-
from rewrite.java.tree import Empty, FieldAccess, Identifier, Import, Space
23+
from rewrite.java.tree import Empty, FieldAccess, Identifier, Import, MethodDeclaration, Space
2424
from rewrite.markers import Markers
2525
from rewrite.python.tree import CompilationUnit, MultiImport
2626
from rewrite.python.visitor import PythonVisitor
@@ -129,6 +129,11 @@ def visit_multi_import(self, multi: MultiImport, p) -> J:
129129

130130
def visit_identifier(self, ident: Identifier, p) -> J:
131131
if not self.in_import:
132+
# Inside a function scope, identifiers with field_type are
133+
# local variables (shadowing the import), not actual uses.
134+
if self.cursor.first_enclosing(MethodDeclaration) is not None:
135+
if ident.field_type is not None:
136+
return ident
132137
used.add(ident.simple_name)
133138
return ident
134139

0 commit comments

Comments
 (0)