Skip to content

Commit b7a680a

Browse files
committed
Fix ChangeType UnsupportedOperationException on JS FunctionCall nodes
ChangeType.postVisit() falls through to the TypedTree branch for JS.FunctionCall nodes, which throws UnsupportedOperationException because withType() is not supported on MethodCall implementations. Add a MethodCall catch-all branch before the TypedTree fallback that uses withMethodType() instead, handling JS.FunctionCall and any other future MethodCall implementations not explicitly handled.
1 parent 5b212d9 commit b7a680a

2 files changed

Lines changed: 74 additions & 0 deletions

File tree

rewrite-java/src/main/java/org/openrewrite/java/ChangeType.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,9 @@ private void addImport(JavaType.FullyQualified owningClass) {
221221
} else if (j instanceof J.NewClass) {
222222
J.NewClass n = (J.NewClass) j;
223223
j = n.withConstructorType(updateType(n.getConstructorType()));
224+
} else if (j instanceof MethodCall) {
225+
MethodCall call = (MethodCall) j;
226+
j = (J) call.withMethodType(updateType(call.getMethodType()));
224227
} else if (tree instanceof TypedTree) {
225228
j = ((TypedTree) tree).withType(updateType(((TypedTree) tree).getType()));
226229
} else if (tree instanceof JavaSourceFile) {
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright 2025 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.javascript;
17+
18+
import org.junit.jupiter.api.Test;
19+
import org.openrewrite.java.ChangeType;
20+
import org.openrewrite.javascript.tree.JS;
21+
import org.openrewrite.test.RewriteTest;
22+
23+
import java.util.concurrent.atomic.AtomicBoolean;
24+
25+
import static org.assertj.core.api.Assertions.assertThat;
26+
import static org.openrewrite.javascript.Assertions.javascript;
27+
28+
/**
29+
* Prove that {@link ChangeType}, written for Java, does not fail on JavaScript source files
30+
* containing {@link JS.FunctionCall} nodes.
31+
*/
32+
class ChangeTypeAdaptabilityTest implements RewriteTest {
33+
34+
@Test
35+
void functionCallDoesNotThrow() {
36+
AtomicBoolean hasFunctionCall = new AtomicBoolean(false);
37+
rewriteRun(
38+
spec -> spec.recipe(new ChangeType("Foo", "Bar", true)),
39+
javascript(
40+
"""
41+
class Foo {
42+
getHandler() {
43+
return function() { return 1; };
44+
}
45+
}
46+
var result = new Foo().getHandler()();
47+
""",
48+
"""
49+
class Foo {
50+
getHandler() {
51+
return function() { return 1; };
52+
}
53+
}
54+
var result = new Bar().getHandler()();
55+
""",
56+
spec -> spec.afterRecipe(cu -> {
57+
new JavaScriptVisitor<Integer>() {
58+
@Override
59+
public JS.FunctionCall visitFunctionCall(JS.FunctionCall functionCall, Integer p) {
60+
hasFunctionCall.set(true);
61+
return functionCall;
62+
}
63+
}.visit(cu, 0);
64+
assertThat(hasFunctionCall.get())
65+
.as("Expected parsed JavaScript to contain a JS.FunctionCall node")
66+
.isTrue();
67+
})
68+
)
69+
);
70+
}
71+
}

0 commit comments

Comments
 (0)