Skip to content

Commit f3a0409

Browse files
ranuradhAnuRam123timtebeek
authored
Replace static com.sun.awt.AWTUtilities methods with Java 11 equivalents (#544)
* recipe replaceComSunAWTUtilitiesClasses * recipe update * Minor polish * Use non-contextSensitive templates instead * Drop method patterns from declarative recipe --------- Co-authored-by: anuram <[email protected]> Co-authored-by: Tim te Beek <[email protected]>
1 parent 33affa2 commit f3a0409

File tree

4 files changed

+360
-3
lines changed

4 files changed

+360
-3
lines changed
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
/*
2+
* Copyright 2024 the original author or authors.
3+
* <p>
4+
* Licensed under the Apache License, Version 2.0 (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://www.apache.org/licenses/LICENSE-2.0
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;
17+
18+
import com.fasterxml.jackson.annotation.JsonCreator;
19+
import lombok.AllArgsConstructor;
20+
import lombok.EqualsAndHashCode;
21+
import lombok.Value;
22+
import org.openrewrite.ExecutionContext;
23+
import org.openrewrite.Option;
24+
import org.openrewrite.Recipe;
25+
import org.openrewrite.TreeVisitor;
26+
import org.openrewrite.java.JavaTemplate;
27+
import org.openrewrite.java.JavaVisitor;
28+
import org.openrewrite.java.MethodMatcher;
29+
import org.openrewrite.java.tree.J;
30+
31+
@Value
32+
@EqualsAndHashCode(callSuper = false)
33+
@AllArgsConstructor
34+
public class ReplaceComSunAWTUtilitiesMethods extends Recipe {
35+
36+
@Option(displayName = "Method pattern to replace",
37+
description = "The method pattern to match and replace.",
38+
example = "com.sun.awt.AWTUtilities isTranslucencySupported(com.sun.awt.AWTUtilities.Translucency)",
39+
required = false)
40+
String getAWTIsWindowsTranslucencyPattern;
41+
42+
43+
@Option(displayName = "Method pattern to replace",
44+
description = "The method pattern to match and replace.",
45+
example = "com.test.AWTUtilities isWindowOpaque(java.awt.Window)",
46+
required = false)
47+
String isWindowOpaquePattern;
48+
49+
@Option(displayName = "Method pattern to replace",
50+
description = "The method pattern to match and replace.",
51+
example = "com.test.AWTUtilities isTranslucencyCapable(java.awt.GraphicsConfiguration)",
52+
required = false)
53+
String isTranslucencyCapablePattern;
54+
55+
@Option(displayName = "Method pattern to replace",
56+
description = "The method pattern to match and replace.",
57+
example = "com.test.AWTUtilities setWindowOpacity(java.awt.Window, float)",
58+
required = false)
59+
String setWindowOpacityPattern;
60+
61+
@Option(displayName = "Method pattern to replace",
62+
description = "The method pattern to match and replace.",
63+
example = "com.test.AWTUtilities getWindowOpacity(java.awt.Window)",
64+
required = false)
65+
String getWindowOpacityPattern;
66+
67+
@Option(displayName = "Method pattern to replace",
68+
description = "The method pattern to match and replace.",
69+
example = "com.test.AWTUtilitiesTest getWindowShape(java.awt.Window)",
70+
required = false)
71+
String getWindowShapePattern;
72+
73+
@Option(displayName = "Method pattern to replace",
74+
description = "The method pattern to match and replace.",
75+
example = "com.test.AWTUtilities setComponentMixingCutoutShape(java.awt.Component,java.awt.Shape)",
76+
required = false)
77+
String setComponentMixingCutoutShapePattern;
78+
79+
@JsonCreator
80+
public ReplaceComSunAWTUtilitiesMethods() {
81+
getAWTIsWindowsTranslucencyPattern = "com.sun.awt.AWTUtilities isTranslucencySupported(com.sun.awt.AWTUtilities.Translucency)";
82+
getWindowOpacityPattern = "com.sun.awt.AWTUtilities getWindowOpacity(java.awt.Window)";
83+
getWindowShapePattern = "com.sun.awt.AWTUtilities getWindowShape(java.awt.Window)";
84+
isWindowOpaquePattern = "com.sun.awt.AWTUtilities isWindowOpaque(java.awt.Window)";
85+
isTranslucencyCapablePattern = "com.sun.awt.AWTUtilities isTranslucencyCapable(java.awt.GraphicsConfiguration)";
86+
setComponentMixingCutoutShapePattern = "com.sun.awt.AWTUtilities setComponentMixingCutoutShape(java.awt.Component,java.awt.Shape)";
87+
setWindowOpacityPattern = "com.sun.awt.AWTUtilities setWindowOpacity(java.awt.Window, float)";
88+
}
89+
90+
@Override
91+
public String getDisplayName() {
92+
return "Replace `com.sun.awt.AWTUtilities` static method invocations";
93+
}
94+
95+
@Override
96+
public String getDescription() {
97+
return "This recipe replaces several static calls in `com.sun.awt.AWTUtilities` with the JavaSE 11 equivalent. " +
98+
"The methods replaced are `AWTUtilities.isTranslucencySupported()`, `AWTUtilities.setWindowOpacity()`, `AWTUtilities.getWindowOpacity()`, " +
99+
"`AWTUtilities.getWindowShape()`, `AWTUtilities.isWindowOpaque()`, `AWTUtilities.isTranslucencyCapable()` and `AWTUtilities.setComponentMixingCutoutShape()`.";
100+
}
101+
102+
@Override
103+
public TreeVisitor<?, ExecutionContext> getVisitor() {
104+
MethodMatcher getAWTIsWindowsTranslucencyMethod = new MethodMatcher(getAWTIsWindowsTranslucencyPattern);
105+
MethodMatcher getWindowOpacityPatternMethod = new MethodMatcher(getWindowOpacityPattern);
106+
MethodMatcher getWindowShapePatternMethod = new MethodMatcher(getWindowShapePattern);
107+
MethodMatcher isWindowOpaquePatternMethod = new MethodMatcher(isWindowOpaquePattern);
108+
MethodMatcher isTranslucencyCapablePatternMethod = new MethodMatcher(isTranslucencyCapablePattern);
109+
MethodMatcher setComponentMixingCutoutShapePatternMethod = new MethodMatcher(setComponentMixingCutoutShapePattern);
110+
MethodMatcher setWindowOpacityPatternMethod = new MethodMatcher(setWindowOpacityPattern);
111+
112+
return new JavaVisitor<ExecutionContext>() {
113+
@Override
114+
public J visitMethodInvocation(J.MethodInvocation mi, ExecutionContext ctx) {
115+
super.visitMethodInvocation(mi, ctx);
116+
if (getAWTIsWindowsTranslucencyMethod.matches(mi)) {
117+
maybeRemoveImport(mi.getMethodType().getDeclaringType().getFullyQualifiedName());
118+
maybeAddImport("java.awt.GraphicsDevice", false);
119+
maybeAddImport("java.awt.GraphicsEnvironment", false);
120+
maybeAddImport("java.awt.Window", false);
121+
maybeAddImport("java.awt.GraphicsDevice.WindowTranslucency", false);
122+
String templateString = "GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().isWindowTranslucencySupported(WindowTranslucency."
123+
+ ((J.FieldAccess) mi.getArguments().get(0)).getSimpleName();
124+
return JavaTemplate.builder(templateString).
125+
imports("java.awt.GraphicsDevice",
126+
"java.awt.GraphicsEnvironment",
127+
"java.awt.Window",
128+
"java.awt.GraphicsDevice.WindowTranslucency")
129+
.build()
130+
.apply(getCursor(), mi.getCoordinates().replace())
131+
.withPrefix(mi.getPrefix());
132+
}
133+
if (isWindowOpaquePatternMethod.matches(mi)) {
134+
maybeRemoveImport(mi.getMethodType().getDeclaringType().getFullyQualifiedName());
135+
return JavaTemplate.builder("#{any()}.isOpaque()")
136+
.build()
137+
.apply(getCursor(), mi.getCoordinates().replace(), mi.getArguments().get(0))
138+
.withPrefix(mi.getPrefix());
139+
}
140+
if (isTranslucencyCapablePatternMethod.matches(mi)) {
141+
maybeRemoveImport(mi.getMethodType().getDeclaringType().getFullyQualifiedName());
142+
return JavaTemplate.builder("#{any()}.isTranslucencyCapable()")
143+
.build()
144+
.apply(getCursor(), mi.getCoordinates().replace(), mi.getArguments().get(0))
145+
.withPrefix(mi.getPrefix());
146+
}
147+
if (setWindowOpacityPatternMethod.matches(mi)) {
148+
maybeRemoveImport(mi.getMethodType().getDeclaringType().getFullyQualifiedName());
149+
return JavaTemplate.builder("#{any()}.setOpacity(#{any()})")
150+
.build()
151+
.apply(getCursor(), mi.getCoordinates().replace(),
152+
mi.getArguments().get(0),
153+
mi.getArguments().get(1))
154+
.withPrefix(mi.getPrefix());
155+
}
156+
if (getWindowOpacityPatternMethod.matches(mi)) {
157+
maybeRemoveImport(mi.getMethodType().getDeclaringType().getFullyQualifiedName());
158+
return JavaTemplate.builder("#{any()}.getOpacity()")
159+
.build()
160+
.apply(getCursor(), mi.getCoordinates().replace(), mi.getArguments().get(0))
161+
.withPrefix(mi.getPrefix());
162+
}
163+
if (getWindowShapePatternMethod.matches(mi)) {
164+
maybeRemoveImport(mi.getMethodType().getDeclaringType().getFullyQualifiedName());
165+
return JavaTemplate.builder("#{any()}.getShape()")
166+
.build()
167+
.apply(getCursor(), mi.getCoordinates().replace(), mi.getArguments().get(0))
168+
.withPrefix(mi.getPrefix());
169+
}
170+
if (setComponentMixingCutoutShapePatternMethod.matches(mi)) {
171+
maybeRemoveImport(mi.getMethodType().getDeclaringType().getFullyQualifiedName());
172+
return JavaTemplate.builder("#{any()}.setMixingCutoutShape(#{any()})")
173+
.build()
174+
.apply(getCursor(), mi.getCoordinates().replace(),
175+
mi.getArguments().get(0),
176+
mi.getArguments().get(1))
177+
.withPrefix(mi.getPrefix());
178+
}
179+
return mi;
180+
}
181+
};
182+
}
183+
}

src/main/java/org/openrewrite/java/migrate/ReplaceLocalizedStreamMethods.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,14 @@ public class ReplaceLocalizedStreamMethods extends Recipe {
3333

3434
@Option(displayName = "Method pattern to replace",
3535
description = "The method pattern to match and replace.",
36-
example = "java.lang.Runtime getLocalizedInputStream(java.io.InputStream)")
36+
example = "java.lang.Runtime getLocalizedInputStream(java.io.InputStream)",
37+
required = false)
3738
String localizedInputStreamMethodMatcher;
3839

3940
@Option(displayName = "Method pattern to replace",
4041
description = "The method pattern to match and replace.",
41-
example = "java.lang.Runtime getLocalizedOutputStream(java.io.OutputStream)")
42+
example = "java.lang.Runtime getLocalizedOutputStream(java.io.OutputStream)",
43+
required = false)
4244
String localizedOutputStreamMethodMatcher;
4345

4446
@JsonCreator

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ recipeList:
7373
getPeerMethodPattern: java.awt.* getPeer()
7474
lightweightPeerFQCN: java.awt.peer.LightweightPeer
7575
- org.openrewrite.scala.migrate.UpgradeScala_2_12
76+
- org.openrewrite.java.migrate.ReplaceComSunAWTUtilitiesMethods
7677
- org.openrewrite.java.migrate.ReplaceLocalizedStreamMethods
77-
7878
---
7979
type: specs.openrewrite.org/v1beta/recipe
8080
name: org.openrewrite.java.migrate.UpgradeBuildToJava11
@@ -290,3 +290,4 @@ recipeList:
290290
- org.openrewrite.java.ChangeMethodName:
291291
methodPattern: java.nio.file.Path get(..)
292292
newMethodName: of
293+
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/*
2+
* Copyright 2024 the original author or authors.
3+
* <p>
4+
* Licensed under the Apache License, Version 2.0 (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://www.apache.org/licenses/LICENSE-2.0
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;
17+
18+
import org.junit.jupiter.api.Test;
19+
import org.openrewrite.DocumentExample;
20+
import org.openrewrite.java.JavaParser;
21+
import org.openrewrite.test.RecipeSpec;
22+
import org.openrewrite.test.RewriteTest;
23+
24+
import static org.openrewrite.java.Assertions.java;
25+
26+
class ReplaceComSunAWTUtilitiesMethodsTest implements RewriteTest {
27+
28+
@Override
29+
public void defaults(RecipeSpec spec) {
30+
spec.recipe(new ReplaceComSunAWTUtilitiesMethods(
31+
"com.test.AWTUtilitiesTest isTranslucencySupported1(com.test.AWTUtilitiesTest.Translucency)",
32+
"com.test.AWTUtilitiesTest isWindowOpaque(java.awt.Window)",
33+
"com.test.AWTUtilitiesTest isTranslucencyCapable(java.awt.GraphicsConfiguration)",
34+
"com.test.AWTUtilitiesTest setWindowOpacity(java.awt.Window,float)",
35+
"com.test.AWTUtilitiesTest getWindowOpacity(java.awt.Window)",
36+
"com.test.AWTUtilitiesTest getWindowShape(java.awt.Window)",
37+
"com.test.AWTUtilitiesTest setComponentMixingCutoutShape(java.awt.Component,java.awt.Shape)"))
38+
.parser(JavaParser.fromJavaVersion()
39+
//language=java
40+
.dependsOn(
41+
"""
42+
package com.test;
43+
44+
import java.awt.Window;
45+
import java.awt.GraphicsConfiguration;
46+
import java.awt.Shape;
47+
import java.awt.Component;
48+
49+
public class AWTUtilitiesTest {
50+
private static final String TRANSLUCENT = "test";
51+
public enum Translucency {
52+
PERPIXEL_TRANSPARENT,
53+
TRANSLUCENT,
54+
PERPIXEL_TRANSLUCENT;
55+
}
56+
public static boolean isTranslucencySupported1(Translucency translucencyKind) {
57+
return true;
58+
}
59+
public static boolean isWindowOpaque(Window win) {
60+
return true;
61+
}
62+
public static boolean isTranslucencyCapable(GraphicsConfiguration gc) {
63+
return true;
64+
}
65+
public static void setWindowOpacity(Window win,float f) {
66+
67+
}
68+
public static float getWindowOpacity(Window win) {
69+
return 1;
70+
}
71+
public static Shape getWindowShape(Window win) {
72+
return null;
73+
}
74+
public static void setComponentMixingCutoutShape(Component c, Shape sh){
75+
76+
}
77+
}
78+
"""
79+
)
80+
);
81+
}
82+
83+
@Test
84+
void replaceComSunAWTUtilitiesClassesIsTranslucencySupported() {
85+
rewriteRun(
86+
//language=java
87+
java(
88+
"""
89+
import com.test.AWTUtilitiesTest;
90+
91+
class Test {
92+
void foo() {
93+
boolean f = AWTUtilitiesTest.isTranslucencySupported1(AWTUtilitiesTest.Translucency.TRANSLUCENT);
94+
boolean j = AWTUtilitiesTest.isTranslucencySupported1(AWTUtilitiesTest.Translucency.PERPIXEL_TRANSPARENT);
95+
boolean k = AWTUtilitiesTest.isTranslucencySupported1(AWTUtilitiesTest.Translucency.PERPIXEL_TRANSLUCENT);
96+
}
97+
}
98+
""",
99+
"""
100+
import java.awt.GraphicsDevice;
101+
import java.awt.GraphicsDevice.WindowTranslucency;
102+
import java.awt.GraphicsEnvironment;
103+
import java.awt.Window;
104+
105+
class Test {
106+
void foo() {
107+
boolean f = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().isWindowTranslucencySupported(WindowTranslucency.TRANSLUCENT);
108+
boolean j = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().isWindowTranslucencySupported(WindowTranslucency.PERPIXEL_TRANSPARENT);
109+
boolean k = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().isWindowTranslucencySupported(WindowTranslucency.PERPIXEL_TRANSLUCENT);
110+
}
111+
}
112+
"""
113+
)
114+
);
115+
}
116+
117+
@Test
118+
@DocumentExample
119+
void replaceComSunAWTUtilitiesClassesRemaining() {
120+
rewriteRun(
121+
//language=java
122+
java(
123+
"""
124+
package com.test;
125+
import com.test.AWTUtilitiesTest;
126+
import java.awt.Window;
127+
import java.awt.*;
128+
import javax.swing.*;
129+
import java.awt.geom.Ellipse2D;
130+
131+
class Test {
132+
void foo() {
133+
Window win = new Window(new JFrame("test"));
134+
boolean f = AWTUtilitiesTest.isWindowOpaque(win);
135+
AWTUtilitiesTest.setWindowOpacity(win,1);
136+
float l = AWTUtilitiesTest.getWindowOpacity(win);
137+
Shape sh = AWTUtilitiesTest.getWindowShape(win);
138+
GraphicsConfiguration gc = null;
139+
boolean f = AWTUtilitiesTest.isTranslucencyCapable(gc);
140+
Component c = null;
141+
Shape sh = new Ellipse2D.Double(0, 0, c.getWidth(), c.getHeight());
142+
AWTUtilitiesTest.setComponentMixingCutoutShape(c, sh);
143+
}
144+
}
145+
""",
146+
"""
147+
package com.test;
148+
import java.awt.Window;
149+
import java.awt.*;
150+
import javax.swing.*;
151+
import java.awt.geom.Ellipse2D;
152+
153+
class Test {
154+
void foo() {
155+
Window win = new Window(new JFrame("test"));
156+
boolean f = win.isOpaque();
157+
win.setOpacity(1);
158+
float l = win.getOpacity();
159+
Shape sh = win.getShape();
160+
GraphicsConfiguration gc = null;
161+
boolean f = gc.isTranslucencyCapable();
162+
Component c = null;
163+
Shape sh = new Ellipse2D.Double(0, 0, c.getWidth(), c.getHeight());
164+
c.setMixingCutoutShape(sh);
165+
}
166+
}
167+
"""
168+
)
169+
);
170+
}
171+
}

0 commit comments

Comments
 (0)