Skip to content

Commit 3f0cbe1

Browse files
authored
Add NumberToDuration recipe to convert numeric type to Duration (#5170)
* Add NumberToDuration recipe to convert numeric type to Duration * Fix test
1 parent 71aeedd commit 3f0cbe1

File tree

2 files changed

+214
-0
lines changed

2 files changed

+214
-0
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
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+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.migration.internal.recipe;
17+
18+
import com.fasterxml.jackson.annotation.JsonCreator;
19+
import com.fasterxml.jackson.annotation.JsonProperty;
20+
import java.util.ArrayList;
21+
import java.util.List;
22+
import java.util.concurrent.TimeUnit;
23+
import org.openrewrite.ExecutionContext;
24+
import org.openrewrite.Option;
25+
import org.openrewrite.Recipe;
26+
import org.openrewrite.TreeVisitor;
27+
import org.openrewrite.java.JavaIsoVisitor;
28+
import org.openrewrite.java.JavaTemplate;
29+
import org.openrewrite.java.MethodMatcher;
30+
import org.openrewrite.java.tree.J;
31+
import software.amazon.awssdk.annotations.SdkInternalApi;
32+
33+
/**
34+
* Convert the method parameter from numeric types to duration.
35+
*/
36+
@SdkInternalApi
37+
public class NumberToDuration extends Recipe {
38+
@Option(displayName = "Method pattern",
39+
description = "A method pattern that is used to find matching method invocations.",
40+
example = "com.amazonaws.ClientConfiguration setRequestTimeout(int)")
41+
private final String methodPattern;
42+
43+
@Option(displayName = "Time Unit",
44+
description = "The TimeUnit enum value to convert. Defaults to `MILLISECONDS`.",
45+
example = "MILLISECONDS",
46+
required = false)
47+
private final TimeUnit timeUnit;
48+
49+
@JsonCreator
50+
public NumberToDuration(@JsonProperty("methodPattern") String methodPattern,
51+
@JsonProperty("timeUnit") TimeUnit timeUnit) {
52+
this.methodPattern = methodPattern;
53+
this.timeUnit = timeUnit == null ? TimeUnit.MILLISECONDS : timeUnit;
54+
}
55+
56+
@Override
57+
public String getDisplayName() {
58+
return "Convert the method parameter from numeric type to duration";
59+
}
60+
61+
@Override
62+
public String getDescription() {
63+
return "Convert the method parameter from numeric types to duration.";
64+
}
65+
66+
@Override
67+
public TreeVisitor<?, ExecutionContext> getVisitor() {
68+
return new Visitor(methodPattern, timeUnit);
69+
}
70+
71+
private static final class Visitor extends JavaIsoVisitor<ExecutionContext> {
72+
private final MethodMatcher methodMatcher;
73+
private final TimeUnit timeUnit;
74+
75+
Visitor(String methodPattern, TimeUnit timeUnit) {
76+
this.methodMatcher = new MethodMatcher(methodPattern, false);
77+
this.timeUnit = timeUnit;
78+
}
79+
80+
@Override
81+
public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) {
82+
J.MethodInvocation methodInvocation = super.visitMethodInvocation(method, ctx);
83+
if (!methodMatcher.matches(methodInvocation)) {
84+
return methodInvocation;
85+
}
86+
87+
String durationStr = durationCreationStr();
88+
89+
JavaTemplate template = JavaTemplate
90+
.builder(durationStr + "(#{})")
91+
.contextSensitive()
92+
.imports("java.time.Duration")
93+
.build();
94+
95+
List<Object> arguments = new ArrayList<>(methodInvocation.getArguments());
96+
97+
methodInvocation = template.apply(
98+
updateCursor(methodInvocation),
99+
methodInvocation.getCoordinates().replaceArguments(),
100+
arguments.toArray(new Object[0])
101+
);
102+
maybeAddImport("java.time.Duration");
103+
return methodInvocation;
104+
}
105+
106+
private String durationCreationStr() {
107+
String durationStr;
108+
switch (timeUnit) {
109+
case MILLISECONDS:
110+
durationStr = "Duration.ofMillis";
111+
break;
112+
case SECONDS:
113+
durationStr = "Duration.ofSeconds";
114+
break;
115+
case MINUTES:
116+
durationStr = "Duration.ofMinutes";
117+
break;
118+
default:
119+
throw new UnsupportedOperationException("Unsupported time unit: " + timeUnit);
120+
}
121+
return durationStr;
122+
}
123+
}
124+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
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+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.migration.internal.recipe;
17+
18+
import static org.openrewrite.java.Assertions.java;
19+
20+
import java.util.concurrent.TimeUnit;
21+
import org.junit.jupiter.api.Test;
22+
import org.junit.jupiter.api.condition.EnabledOnJre;
23+
import org.junit.jupiter.api.condition.JRE;
24+
import org.openrewrite.java.Java8Parser;
25+
import org.openrewrite.test.RewriteTest;
26+
27+
public class NumberToDurationTest implements RewriteTest {
28+
29+
@Test
30+
@EnabledOnJre({JRE.JAVA_8})
31+
void timeUnitNotSpecified_shouldUseMilliSeconds() {
32+
rewriteRun(
33+
spec -> spec.recipe(new NumberToDuration("com.amazonaws.ClientConfiguration setRequestTimeout(int)",
34+
null))
35+
.parser(Java8Parser.builder().classpath("sqs", "aws-core", "sdk-core", "aws-java-sdk-sqs")),
36+
java(
37+
"import com.amazonaws.ClientConfiguration;\n"
38+
+ "\n"
39+
+ "public class Example {\n"
40+
+ " \n"
41+
+ " void test() {\n"
42+
+ " ClientConfiguration clientConfiguration = new ClientConfiguration();\n"
43+
+ " clientConfiguration.setRequestTimeout(1000);\n"
44+
+ " }\n"
45+
+ "}\n",
46+
"import com.amazonaws.ClientConfiguration;\n\n"
47+
+ "import java.time.Duration;\n"
48+
+ "\n"
49+
+ "public class Example {\n"
50+
+ " \n"
51+
+ " void test() {\n"
52+
+ " ClientConfiguration clientConfiguration = new ClientConfiguration();\n"
53+
+ " clientConfiguration.setRequestTimeout(Duration.ofMillis(1000));\n"
54+
+ " }\n"
55+
+ "}"
56+
)
57+
);
58+
}
59+
60+
@Test
61+
@EnabledOnJre({JRE.JAVA_8})
62+
void timeUnitSpecified_shouldHonor() {
63+
rewriteRun(
64+
spec -> spec.recipe(new NumberToDuration("com.amazonaws.ClientConfiguration setRequestTimeout(int)",
65+
TimeUnit.SECONDS))
66+
.parser(Java8Parser.builder().classpath("sqs", "aws-core", "sdk-core", "aws-java-sdk-sqs")),
67+
java(
68+
"import com.amazonaws.ClientConfiguration;\n"
69+
+ "\n"
70+
+ "public class Example {\n"
71+
+ " \n"
72+
+ " void test() {\n"
73+
+ " ClientConfiguration clientConfiguration = new ClientConfiguration();\n"
74+
+ " clientConfiguration.setRequestTimeout(1000);\n"
75+
+ " }\n"
76+
+ "}\n",
77+
"import com.amazonaws.ClientConfiguration;\n\n"
78+
+ "import java.time.Duration;\n"
79+
+ "\n"
80+
+ "public class Example {\n"
81+
+ " \n"
82+
+ " void test() {\n"
83+
+ " ClientConfiguration clientConfiguration = new ClientConfiguration();\n"
84+
+ " clientConfiguration.setRequestTimeout(Duration.ofSeconds(1000));\n"
85+
+ " }\n"
86+
+ "}"
87+
)
88+
);
89+
}
90+
}

0 commit comments

Comments
 (0)