Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion rewrite-csharp/csharp/OpenRewrite/Java/Rpc/JavaReceiver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,8 @@ public override J VisitClassDeclaration(ClassDeclaration classDecl, RpcReceiveQu
var implements_ = q.Receive(classDecl.Implements, c => VisitContainer(c, q));
var permits = q.Receive(classDecl.Permits, c => VisitContainer(c, q));
var body = q.Receive((J)classDecl.Body, el => (J)VisitNonNull(el, q));
return classDecl.WithId(_pvId).WithPrefix(_pvPrefix).WithMarkers(_pvMarkers).WithLeadingAnnotations(leadingAnnotations!).WithModifiers(modifiers!).WithClassKind((ClassDeclaration.Kind)kind!).WithName((Identifier)name!).WithTypeParameters(typeParameters).WithPrimaryConstructor(primaryConstructor).WithExtends(extends_).WithImplements(implements_).WithPermits(permits).WithBody((Block)body!);
var type = q.Receive(classDecl.Type, t => (JavaType.FullyQualified?)VisitType(t, q));
return classDecl.WithId(_pvId).WithPrefix(_pvPrefix).WithMarkers(_pvMarkers).WithLeadingAnnotations(leadingAnnotations!).WithModifiers(modifiers!).WithClassKind((ClassDeclaration.Kind)kind!).WithName((Identifier)name!).WithTypeParameters(typeParameters).WithPrimaryConstructor(primaryConstructor).WithExtends(extends_).WithImplements(implements_).WithPermits(permits).WithBody((Block)body!).WithType(type);
}

private J VisitClassDeclarationKind(ClassDeclaration.Kind kind, RpcReceiveQueue q)
Expand Down
1 change: 1 addition & 0 deletions rewrite-csharp/csharp/OpenRewrite/Java/Rpc/JavaSender.cs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ public override J VisitClassDeclaration(ClassDeclaration classDecl, RpcSendQueue
q.GetAndSend(classDecl, c => c.Implements, impl => VisitContainer(impl, q));
q.GetAndSend(classDecl, c => c.Permits, perm => VisitContainer(perm, q));
q.GetAndSend(classDecl, c => (J)c.Body, j => Visit(j, q));
q.GetAndSend(classDecl, c => AsRef(c.Type), type => VisitType(GetValueNonNull<JavaType>(type), q));
return classDecl;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,9 @@ private void addImport(JavaType.FullyQualified owningClass) {
} else if (j instanceof J.NewClass) {
J.NewClass n = (J.NewClass) j;
j = n.withConstructorType(updateType(n.getConstructorType()));
} else if (j instanceof MethodCall) {
MethodCall call = (MethodCall) j;
j = (J) call.withMethodType(updateType(call.getMethodType()));
} else if (tree instanceof TypedTree) {
j = ((TypedTree) tree).withType(updateType(((TypedTree) tree).getType()));
} else if (tree instanceof JavaSourceFile) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ public J visitClassDeclaration(J.ClassDeclaration classDecl, RpcReceiveQueue q)
.getPadding().withExtends(q.receive(classDecl.getPadding().getExtends(), e -> visitLeftPadded(e, q)))
.getPadding().withImplements(q.receive(classDecl.getPadding().getImplements(), i -> visitContainer(i, q)))
.getPadding().withPermits(q.receive(classDecl.getPadding().getPermits(), p -> visitContainer(p, q)))
.withBody(q.receive(classDecl.getBody(), b -> (J.Block) visitNonNull(b, q)));
.withBody(q.receive(classDecl.getBody(), b -> (J.Block) visitNonNull(b, q)))
.withType(q.receive(classDecl.getType(), t -> (JavaType.FullyQualified) visitType(t, q)));
}

private J.ClassDeclaration.Kind visitClassDeclarationKind(J.ClassDeclaration.Kind kind, RpcReceiveQueue q) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ public J visitClassDeclaration(J.ClassDeclaration classDecl, RpcSendQueue q) {
q.getAndSend(classDecl, c -> c.getPadding().getImplements(), impl -> visitContainer(impl, q));
q.getAndSend(classDecl, c -> c.getPadding().getPermits(), impl -> visitContainer(impl, q));
q.getAndSend(classDecl, J.ClassDeclaration::getBody, j -> visit(j, q));
q.getAndSend(classDecl, c -> asRef(c.getType()), type -> visitType(getValueNonNull(type), q));
return classDecl;
}

Expand Down
4 changes: 3 additions & 1 deletion rewrite-javascript/rewrite/src/java/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,7 @@ export class JavaSender extends JavaVisitor<RpcSendQueue> {
await q.getAndSend(cls, c => c.implements, impl => this.visitContainer(impl, q));
await q.getAndSend(cls, c => c.permitting, perm => this.visitContainer(perm, q));
await q.getAndSend(cls, c => c.body, body => this.visit(body, q));
await q.getAndSend(cls, c => asRef(c.type), type => this.visitType(type, q));
return cls;
}

Expand Down Expand Up @@ -1435,7 +1436,8 @@ export class JavaReceiver extends JavaVisitor<RpcReceiveQueue> {
extends: await q.receive(cls.extends, ext => this.visitLeftPadded(ext, q)),
implements: await q.receive(cls.implements, impl => this.visitContainer(impl, q)),
permitting: await q.receive(cls.permitting, perm => this.visitContainer(perm, q)),
body: await q.receive(cls.body, body => this.visit(body, q))
body: await q.receive(cls.body, body => this.visit(body, q)),
type: await q.receive(cls.type, type => this.visitType(type, q)) as Type.Class
};
return updateIfChanged(cls, updates);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright 2025 the original author or authors.
* <p>
* Licensed under the Moderne Source Available License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* https://docs.moderne.io/licensing/moderne-source-available-license
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openrewrite.javascript;

import org.junit.jupiter.api.Test;
import org.openrewrite.java.ChangeType;
import org.openrewrite.java.tree.J;
import org.openrewrite.javascript.tree.JS;
import org.openrewrite.test.RewriteTest;

import java.util.concurrent.atomic.AtomicBoolean;

import static org.assertj.core.api.Assertions.assertThat;
import static org.openrewrite.javascript.Assertions.javascript;

/**
* Prove that {@link ChangeType}, written for Java, does not fail on JavaScript source files
* containing {@link JS.FunctionCall} nodes.
*/
class ChangeTypeAdaptabilityTest implements RewriteTest {

@Test
void functionCallDoesNotThrow() {
AtomicBoolean hasFunctionCall = new AtomicBoolean(false);
rewriteRun(
spec -> spec.recipe(new ChangeType("Foo", "Bar", false)),
javascript(
"""
class Foo {
getHandler() {
return function() { return 1; };
}
}
var result = new Foo().getHandler()();
""",
"""
class Bar {
getHandler() {
return function() { return 1; };
}
}
var result = new Bar().getHandler()();
""",
spec -> spec.afterRecipe(cu -> {
new JavaScriptVisitor<Integer>() {
@Override
public JS.FunctionCall visitFunctionCall(JS.FunctionCall functionCall, Integer p) {
hasFunctionCall.set(true);
return functionCall;
}
}.visit(cu, 0);
assertThat(hasFunctionCall.get())
.as("Expected parsed JavaScript to contain a JS.FunctionCall node")
.isTrue();
assertThat(cu.getClasses().getFirst().getType())
.as("Expected JS ClassDeclaration to have type attribution")
.isNotNull();
})
)
);
}
}
3 changes: 2 additions & 1 deletion rewrite-python/rewrite/src/rewrite/rpc/python_receiver.py
Original file line number Diff line number Diff line change
Expand Up @@ -727,10 +727,11 @@ def _visit_j_class_declaration(self, class_decl, q: RpcReceiveQueue):
lambda c: self._receive_container(c, q) if c else None
)
body = q.receive(class_decl.body)
type_ = q.receive(class_decl.type)
return replace_if_changed(class_decl, leading_annotations=leading_annotations, modifiers=modifiers,
kind=kind, name=name, type_parameters=type_parameters,
primary_constructor=primary_constructor, extends=extends, implements=implements,
permits=permits, body=body)
permits=permits, body=body, type=type_)

def _visit_j_class_declaration_kind(self, kind, q: RpcReceiveQueue):
from rewrite.java.tree import ClassDeclaration
Expand Down
1 change: 1 addition & 0 deletions rewrite-python/rewrite/src/rewrite/rpc/python_sender.py
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,7 @@ def _visit_j_class_declaration(self, class_decl, q: 'RpcSendQueue') -> None:
q.get_and_send(class_decl, lambda x: x.padding.permits if hasattr(x.padding, 'permits') else None,
lambda c: self._visit_container(c, q) if c else None)
q.get_and_send(class_decl, lambda x: x.body, lambda el: self._visit(el, q))
q.get_and_send_as_ref(class_decl, lambda x: x.type, lambda t: self._visit_type(t, q) if t else None)

def _visit_j_class_declaration_kind(self, kind, q: 'RpcSendQueue') -> None:
# Java ClassDeclaration.Kind: preVisit IS automatically called by _visit before this method
Expand Down