-
Notifications
You must be signed in to change notification settings - Fork 78
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Recipe ReplaceAWTGetPeerMethod in Java 11 Migration (#524)
* getPeer() recipe * updated with fixes * small updates * Apply suggestions from code review Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Apply suggestions from code review * Apply formatter & order imports * Align before and after code blocks again * updated recipe name, updated tests and formatted code * removing extra file commit and test update * adding comments, Test file cleanup * Demonstrate the need for `super.visitControlParentheses(cp, ctx)` * Only override `visitBinary` and `visitInstanceOf` * Update src/test/java/org/openrewrite/java/migrate/ReplaceAWTGetPeerMethodTest.java * update to code and adding missing arguments to .yml * right format for java-version.yml * Remove import after instanceof replacement * Also handle flipped case * Replace `checkClassNameIsEqualToFQCN` with TypeUtils * Remove duplication in arguments * Document options and shorten description * fixed small typo in description --------- Co-authored-by: anuram <ranuradh@us.ibm.com> Co-authored-by: Tim te Beek <tim@moderne.io> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
- Loading branch information
1 parent
7b360b9
commit cdba5a2
Showing
3 changed files
with
264 additions
and
2 deletions.
There are no files selected for viewing
119 changes: 119 additions & 0 deletions
119
src/main/java/org/openrewrite/java/migrate/ReplaceAWTGetPeerMethod.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
/* | ||
* Copyright 2024 the original author or authors. | ||
* <p> | ||
* Licensed under the Apache License, Version 2.0 (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://www.apache.org/licenses/LICENSE-2.0 | ||
* <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.java.migrate; | ||
|
||
import lombok.EqualsAndHashCode; | ||
import lombok.Value; | ||
import org.openrewrite.*; | ||
import org.openrewrite.internal.lang.Nullable; | ||
import org.openrewrite.java.ChangeMethodName; | ||
import org.openrewrite.java.JavaVisitor; | ||
import org.openrewrite.java.MethodMatcher; | ||
import org.openrewrite.java.search.UsesMethod; | ||
import org.openrewrite.java.tree.J; | ||
import org.openrewrite.java.tree.TypeUtils; | ||
import org.openrewrite.java.tree.TypedTree; | ||
|
||
@Value | ||
@EqualsAndHashCode(callSuper = false) | ||
class ReplaceAWTGetPeerMethod extends Recipe { | ||
|
||
@Option(displayName = "Method pattern to replace", | ||
description = "The method pattern to match and replace.", | ||
example = "java.awt.* getPeer()") | ||
String getPeerMethodPattern; | ||
|
||
@Option(displayName = "The LightweightPeer interface FQCN", | ||
description = "The fully qualified class name of the LightweightPeer interface to replace in `instanceof`.", | ||
example = "java.awt.peer.LightweightPeer") | ||
String lightweightPeerFQCN; | ||
|
||
@Override | ||
public String getDisplayName() { | ||
return "Replace AWT `getPeer()` method"; | ||
} | ||
|
||
@Override | ||
public String getDescription() { | ||
return "This recipe replaces the use of `getPeer()` method in `java.awt.*` classes. " + | ||
"`component.getPeer() != null` is replaced with `component.isDisplayable()` and " + | ||
"`component.getPeer() instanceof LightweightPeer` is replaced with `component.isLightweight()`."; | ||
} | ||
|
||
@Override | ||
public TreeVisitor<?, ExecutionContext> getVisitor() { | ||
MethodMatcher methodMatcherGetPeer = new MethodMatcher(getPeerMethodPattern); | ||
return Preconditions.check(new UsesMethod<>(methodMatcherGetPeer), new JavaVisitor<ExecutionContext>() { | ||
@Override | ||
public J visitBinary(J.Binary binary, ExecutionContext ctx) { | ||
J.Binary bi = (J.Binary) super.visitBinary(binary, ctx); | ||
|
||
J.MethodInvocation mi = findMatchingMethodInvocation(bi); | ||
if (mi != null) { | ||
mi = (J.MethodInvocation) new ChangeMethodName( | ||
getPeerMethodPattern, "isDisplayable", true, null) | ||
.getVisitor().visit(mi, ctx); | ||
mi = (J.MethodInvocation) new ChangeMethodInvocationReturnType( | ||
getPeerMethodPattern.split(" ")[0] + " isDisplayable()", "boolean") | ||
.getVisitor().visit(mi, ctx); | ||
assert mi != null; | ||
return mi.withPrefix(bi.getPrefix()); | ||
} | ||
|
||
return bi; | ||
} | ||
|
||
private @Nullable J.MethodInvocation findMatchingMethodInvocation(J.Binary binaryCondition) { | ||
J.MethodInvocation mi = null; | ||
if (binaryCondition.getOperator() == J.Binary.Type.NotEqual) { | ||
if (binaryCondition.getLeft() instanceof J.MethodInvocation && | ||
binaryCondition.getRight() instanceof J.Literal) { | ||
mi = (J.MethodInvocation) binaryCondition.getLeft(); | ||
} else if (binaryCondition.getLeft() instanceof J.Literal && | ||
binaryCondition.getRight() instanceof J.MethodInvocation) { | ||
mi = (J.MethodInvocation) binaryCondition.getRight(); | ||
} | ||
} | ||
if (methodMatcherGetPeer.matches(mi)) { | ||
return mi; | ||
} | ||
return null; | ||
} | ||
|
||
@Override | ||
public J visitInstanceOf(J.InstanceOf instOf, ExecutionContext ctx) { | ||
J.InstanceOf instanceOfVar = (J.InstanceOf) super.visitInstanceOf(instOf, ctx); | ||
|
||
if (instanceOfVar.getExpression() instanceof J.MethodInvocation) { | ||
J.MethodInvocation mi = ((J.MethodInvocation) instanceOfVar.getExpression()); | ||
if (methodMatcherGetPeer.matches(mi) && TypeUtils.isAssignableTo(lightweightPeerFQCN, ((TypedTree) instanceOfVar.getClazz()).getType())) { | ||
mi = (J.MethodInvocation) new ChangeMethodName(getPeerMethodPattern, "isLightweight", true, null) | ||
.getVisitor().visit(mi, ctx); | ||
mi = (J.MethodInvocation) new ChangeMethodInvocationReturnType( | ||
getPeerMethodPattern.split(" ")[0] + " isLightweight()", "boolean") | ||
.getVisitor().visit(mi, ctx); | ||
assert mi != null; | ||
maybeRemoveImport(lightweightPeerFQCN); | ||
return mi.withPrefix(instanceOfVar.getPrefix()); | ||
} | ||
} | ||
|
||
return instanceOfVar; | ||
} | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
141 changes: 141 additions & 0 deletions
141
src/test/java/org/openrewrite/java/migrate/ReplaceAWTGetPeerMethodTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
/* | ||
* Copyright 2024 the original author or authors. | ||
* <p> | ||
* Licensed under the Apache License, Version 2.0 (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://www.apache.org/licenses/LICENSE-2.0 | ||
* <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.java.migrate; | ||
|
||
import org.junit.jupiter.api.Test; | ||
import org.openrewrite.DocumentExample; | ||
import org.openrewrite.java.JavaParser; | ||
import org.openrewrite.test.RecipeSpec; | ||
import org.openrewrite.test.RewriteTest; | ||
|
||
import static org.openrewrite.java.Assertions.java; | ||
|
||
@SuppressWarnings("StatementWithEmptyBody") | ||
class ReplaceAWTGetPeerMethodTest implements RewriteTest { | ||
@Override | ||
public void defaults(RecipeSpec spec) { | ||
spec.recipe(new ReplaceAWTGetPeerMethod("com.test.Component1 getPeer()", "com.test.TestDummy")) | ||
.parser(JavaParser.fromJavaVersion() | ||
//language=java | ||
.dependsOn( | ||
""" | ||
package com.test; | ||
public class Component1 { | ||
public String getPeer() { | ||
return "x"; | ||
} | ||
public boolean isDisplayable() { | ||
return true; | ||
} | ||
public boolean isLightweight() { | ||
return true; | ||
} | ||
} | ||
""", | ||
""" | ||
package com.test; | ||
public class TestDummy { | ||
} | ||
""" | ||
) | ||
); | ||
} | ||
|
||
@Test | ||
@DocumentExample | ||
void instanceAndGetPeerMethodControlParentheses() { | ||
rewriteRun( | ||
//language=java | ||
java( | ||
""" | ||
import com.test.Component1; | ||
import com.test.TestDummy; | ||
class Test { | ||
void foo() { | ||
Test t1 = new Test(); | ||
Component1 c = new Component1(); | ||
if (c.getPeer() instanceof com.test.TestDummy) { | ||
} | ||
if (c.getPeer() instanceof TestDummy) { | ||
} | ||
Component1 y = new Component1(); | ||
if (y.getPeer() != null) { | ||
} | ||
if (null != y.getPeer()) { | ||
} | ||
} | ||
} | ||
""", | ||
""" | ||
import com.test.Component1; | ||
class Test { | ||
void foo() { | ||
Test t1 = new Test(); | ||
Component1 c = new Component1(); | ||
if (c.isLightweight()) { | ||
} | ||
if (c.isLightweight()) { | ||
} | ||
Component1 y = new Component1(); | ||
if (y.isDisplayable()) { | ||
} | ||
if (y.isDisplayable()) { | ||
} | ||
} | ||
} | ||
""" | ||
) | ||
); | ||
} | ||
|
||
@Test | ||
void instanceAndGetPeerMethodNoParenthesis() { | ||
rewriteRun( | ||
//language=java | ||
java( | ||
""" | ||
import com.test.Component1; | ||
import com.test.TestDummy; | ||
class Test { | ||
void foo() { | ||
Component1 y = new Component1(); | ||
boolean instance = y.getPeer() instanceof TestDummy; | ||
if (instance){ | ||
} | ||
boolean instance1 = y.getPeer() != null; | ||
if (instance1){ | ||
} | ||
} | ||
} | ||
""", | ||
""" | ||
import com.test.Component1; | ||
class Test { | ||
void foo() { | ||
Component1 y = new Component1(); | ||
boolean instance = y.isLightweight(); | ||
if (instance){ | ||
} | ||
boolean instance1 = y.isDisplayable(); | ||
if (instance1){ | ||
} | ||
} | ||
} | ||
""" | ||
) | ||
); | ||
} | ||
} |