Skip to content

Commit 32f2a76

Browse files
committed
Handle wildcard imports in ChangeSdkType recipe
1 parent 77efad7 commit 32f2a76

File tree

4 files changed

+99
-25
lines changed

4 files changed

+99
-25
lines changed

migration-tool/src/main/java/software/amazon/awssdk/migration/internal/utils/NamingConversionUtils.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ public static String getV2Equivalent(String currentFqcn) {
4646
return v2PackagePrefix + "." + v2ClassName;
4747
}
4848

49+
public static String getV2ModelPackageWildCardEquivalent(String currentFqcn) {
50+
int lastIndexOfDot = currentFqcn.lastIndexOf(".");
51+
String packagePrefix = currentFqcn.substring(0, lastIndexOfDot);
52+
String v2PackagePrefix = packagePrefix.replace(V1_PACKAGE_PREFIX, V2_PACKAGE_PREFIX);
53+
return v2PackagePrefix + ".*";
54+
}
55+
4956
private static String getV2ClientOrExceptionEquivalent(String className) {
5057
if (className.startsWith("Abstract")) {
5158
className = className.substring(8);

migration-tool/src/main/java/software/amazon/awssdk/migration/recipe/ChangeSdkType.java

Lines changed: 56 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@
1616
package software.amazon.awssdk.migration.recipe;
1717

1818
import static software.amazon.awssdk.migration.internal.utils.NamingConversionUtils.getV2Equivalent;
19+
import static software.amazon.awssdk.migration.internal.utils.NamingConversionUtils.getV2ModelPackageWildCardEquivalent;
1920
import static software.amazon.awssdk.migration.internal.utils.SdkTypeUtils.isV1ClientClass;
2021
import static software.amazon.awssdk.migration.internal.utils.SdkTypeUtils.isV1ModelClass;
2122

23+
import java.util.ArrayList;
2224
import java.util.HashMap;
2325
import java.util.HashSet;
2426
import java.util.IdentityHashMap;
27+
import java.util.List;
2528
import java.util.Map;
2629
import java.util.Optional;
2730
import java.util.Set;
@@ -55,8 +58,8 @@
5558
*/
5659
@SdkInternalApi
5760
public class ChangeSdkType extends Recipe {
58-
59-
private static final String V1_PATTERN = "com.amazonaws.services.";
61+
private static final String V1_SERVICE_MODEL_WILD_CARD_CLASS_PATTERN = "com\\.amazonaws\\.services\\.[a-zA-Z0-9]+\\.model\\"
62+
+ ".\\*";
6063

6164
@Override
6265
public String getDisplayName() {
@@ -79,6 +82,7 @@ private static class ChangeTypeVisitor extends JavaVisitor<ExecutionContext> {
7982

8083
private final Map<JavaType, JavaType> oldNameToChangedType = new IdentityHashMap<>();
8184
private final Set<String> topLevelClassnames = new HashSet<>();
85+
private final List<String> wildcardImports = new ArrayList<>();
8286

8387
private Map<String, Pair<JavaType.Class, JavaType>> oldTypeToNewType = new HashMap<>();
8488

@@ -99,19 +103,19 @@ public J visitImport(J.Import anImport, ExecutionContext ctx) {
99103
.map(TypeUtils::asFullyQualified)
100104
.orElse(null);
101105

102-
if (fullyQualified == null) {
106+
if (fullyQualified == null) {
107+
String fullName = anImport.getTypeName();
108+
if (fullName.matches(V1_SERVICE_MODEL_WILD_CARD_CLASS_PATTERN)) {
109+
maybeAddImport(getV2ModelPackageWildCardEquivalent(fullName), false);
110+
wildcardImports.add(fullName);
111+
}
103112
return anImport;
104113
}
105114

106115
String currentFqcn = fullyQualified.getFullyQualifiedName();
107116

108-
if (isV1ModelClass(fullyQualified) || isV1ClientClass(fullyQualified)) {
109-
JavaType.ShallowClass originalType = JavaType.ShallowClass.build(currentFqcn);
110-
String v2Equivalent = getV2Equivalent(currentFqcn);
111-
112-
JavaType targetType = JavaType.buildType(v2Equivalent);
113-
114-
oldTypeToNewType.put(currentFqcn, Pair.of(originalType, targetType));
117+
if (isV1Class(fullyQualified)) {
118+
storeV1ClassMetadata(currentFqcn);
115119
if (anImport.getAlias() != null) {
116120
importAlias = anImport.getAlias();
117121
}
@@ -120,6 +124,10 @@ public J visitImport(J.Import anImport, ExecutionContext ctx) {
120124
return anImport;
121125
}
122126

127+
private static boolean isV1Class(JavaType.FullyQualified fullyQualified) {
128+
return isV1ModelClass(fullyQualified) || isV1ClientClass(fullyQualified);
129+
}
130+
123131
@Override
124132
public J visitCompilationUnit(J.CompilationUnit cu, ExecutionContext executionContext) {
125133
return super.visitCompilationUnit(cu, executionContext);
@@ -230,6 +238,11 @@ private J postVisitSourceFile(JavaSourceFile tree, ExecutionContext ctx, J curre
230238

231239
currentTree = sourceFile;
232240
}
241+
242+
for (String fqcn : wildcardImports) {
243+
currentTree = new RemoveImport<ExecutionContext>(fqcn).visit(sourceFile, ctx, getCursor().getParentOrThrow());
244+
}
245+
233246
return currentTree;
234247
}
235248

@@ -281,33 +294,50 @@ public J visitFieldAccess(J.FieldAccess fieldAccess, ExecutionContext ctx) {
281294
public J visitIdentifier(J.Identifier ident, ExecutionContext ctx) {
282295

283296
JavaType currentType = ident.getType();
284-
if (currentType instanceof JavaType.FullyQualified) {
285-
JavaType.FullyQualified original = TypeUtils.asFullyQualified(currentType);
297+
if (!(currentType instanceof JavaType.FullyQualified)) {
298+
return visitAndCast(ident, ctx, super::visitIdentifier);
299+
}
286300

287-
if (original != null && TypeUtils.isOfClassType(ident.getType(), original.getFullyQualifiedName())) {
288-
String fullyQualifiedName = original.getFullyQualifiedName();
301+
JavaType.FullyQualified original = TypeUtils.asFullyQualified(currentType);
289302

290-
if (oldTypeToNewType.containsKey(fullyQualifiedName)) {
291-
JavaType.Class originalType = oldTypeToNewType.get(fullyQualifiedName).left();
292-
String className = originalType.getClassName();
303+
if (original != null && TypeUtils.isOfClassType(ident.getType(), original.getFullyQualifiedName())) {
304+
String fullyQualifiedName = original.getFullyQualifiedName();
293305

294-
if (ident.getSimpleName().equals(className)) {
295-
JavaType targetType = oldTypeToNewType.get(fullyQualifiedName).right();
296-
ident = ident.withSimpleName(((JavaType.FullyQualified) targetType).getClassName());
297-
ident = ident.withType(updateType(currentType));
298-
}
306+
if (isV1Class(original)) {
307+
storeV1ClassMetadata(fullyQualifiedName);
308+
JavaType.Class originalType = oldTypeToNewType.get(fullyQualifiedName).left();
309+
String className = originalType.getClassName();
310+
311+
if (ident.getSimpleName().equals(className)) {
312+
JavaType targetType = oldTypeToNewType.get(fullyQualifiedName).right();
313+
ident = ident.withSimpleName(((JavaType.FullyQualified) targetType).getClassName());
314+
ident = ident.withType(updateType(currentType));
299315
}
300316
}
301317
}
302318

303319
return visitAndCast(ident, ctx, super::visitIdentifier);
304320
}
305321

322+
private void storeV1ClassMetadata(String currentFqcn) {
323+
JavaType.ShallowClass originalType = JavaType.ShallowClass.build(currentFqcn);
324+
String v2Equivalent = getV2Equivalent(currentFqcn);
325+
326+
JavaType targetType = JavaType.buildType(v2Equivalent);
327+
328+
oldTypeToNewType.put(currentFqcn, Pair.of(originalType, targetType));
329+
}
330+
306331
@Override
307332
public J visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) {
308-
for (Pair<JavaType.Class, JavaType> entry : oldTypeToNewType.values()) {
309-
JavaType.Class originalType = entry.left();
310-
JavaType targetType = entry.right();
333+
JavaType.FullyQualified declaringType = method.getMethodType().getDeclaringType();
334+
if (isV1Class(declaringType)) {
335+
String fullyQualifiedName = declaringType.getFullyQualifiedName();
336+
storeV1ClassMetadata(fullyQualifiedName);
337+
338+
Pair<JavaType.Class, JavaType> oldTypeToNewTypePair = oldTypeToNewType.get(fullyQualifiedName);
339+
JavaType.Class originalType = oldTypeToNewTypePair.left();
340+
JavaType targetType = oldTypeToNewTypePair.right();
311341
if (method.getMethodType() != null && method.getMethodType().hasFlags(Flag.Static)) {
312342
if (method.getMethodType().getDeclaringType().isAssignableFrom(originalType)) {
313343
JavaSourceFile cu = getCursor().firstEnclosingOrThrow(JavaSourceFile.class);
@@ -329,6 +359,7 @@ public J visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx)
329359
}
330360
}
331361
}
362+
332363
return super.visitMethodInvocation(method, ctx);
333364
}
334365

migration-tool/src/test/java/software/amazon/awssdk/migration/internal/utils/NamingConversionUtilsTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,10 @@ void v1Exception_shouldConvertToV2() {
7878
assertThat(NamingConversionUtils.getV2Equivalent("com.amazonaws.services.iot.AmazonIOTException"))
7979
.isEqualTo("software.amazon.awssdk.services.iot.IotException");
8080
}
81+
82+
@Test
83+
void v2WildCardImport_shouldConvertToV2() {
84+
assertThat(NamingConversionUtils.getV2ModelPackageWildCardEquivalent("com.amazonaws.services.iot.model.*"))
85+
.isEqualTo("software.amazon.awssdk.services.iot.model.*");
86+
}
8187
}

migration-tool/src/test/java/software/amazon/awssdk/migration/recipe/ChangeSdkTypeTest.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,36 @@ void shouldChangeVariables() {
7272
);
7373
}
7474

75+
@Test
76+
@EnabledOnJre({JRE.JAVA_8})
77+
void wildCardImport_shouldRewrite() {
78+
rewriteRun(
79+
java(
80+
"import com.amazonaws.services.sqs.model.*;\n" +
81+
"class Test {\n" +
82+
" private DeleteQueueResult deleteQueResult;\n" +
83+
" static void method(CreateQueueResult createQueueResult) {\n" +
84+
" ListQueuesRequest request = null;\n" +
85+
" ListQueuesResult result = null;\n" +
86+
" InvalidAttributeNameException exception = null;\n" +
87+
" AmazonSQSException baseException = null;\n" +
88+
" }\n" +
89+
"}\n",
90+
"import software.amazon.awssdk.services.sqs.model.*;\n"
91+
+ "\n"
92+
+ "class Test {\n"
93+
+ " private DeleteQueueResponse deleteQueResult;\n"
94+
+ " static void method(CreateQueueResponse createQueueResult) {\n"
95+
+ " ListQueuesRequest request = null;\n"
96+
+ " ListQueuesResponse result = null;\n"
97+
+ " InvalidAttributeNameException exception = null;\n"
98+
+ " SqsException baseException = null;\n"
99+
+ " }\n"
100+
+ "}"
101+
)
102+
);
103+
}
104+
75105
@Test
76106
@EnabledOnJre({JRE.JAVA_8})
77107
void shouldChangeFields() {

0 commit comments

Comments
 (0)