Skip to content

Commit e7374f9

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

File tree

4 files changed

+121
-28
lines changed

4 files changed

+121
-28
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: 72 additions & 28 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,9 @@
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 =
62+
"com\\.amazonaws\\.services\\.[a-zA-Z0-9]+\\.model\\.\\*";
63+
private static final String V1_SERVICE_WILD_CARD_CLASS_PATTERN = "com\\.amazonaws\\.services\\.[a-zA-Z0-9]+\\.\\*";
6064

6165
@Override
6266
public String getDisplayName() {
@@ -79,6 +83,7 @@ private static class ChangeTypeVisitor extends JavaVisitor<ExecutionContext> {
7983

8084
private final Map<JavaType, JavaType> oldNameToChangedType = new IdentityHashMap<>();
8185
private final Set<String> topLevelClassnames = new HashSet<>();
86+
private final List<String> wildcardImports = new ArrayList<>();
8287

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

@@ -99,19 +104,19 @@ public J visitImport(J.Import anImport, ExecutionContext ctx) {
99104
.map(TypeUtils::asFullyQualified)
100105
.orElse(null);
101106

102-
if (fullyQualified == null) {
107+
if (fullyQualified == null) {
108+
String fullName = anImport.getTypeName();
109+
if (isWildcard(fullName)) {
110+
maybeAddImport(getV2ModelPackageWildCardEquivalent(fullName));
111+
wildcardImports.add(fullName);
112+
}
103113
return anImport;
104114
}
105115

106116
String currentFqcn = fullyQualified.getFullyQualifiedName();
107117

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));
118+
if (isV1Class(fullyQualified)) {
119+
storeV1ClassMetadata(currentFqcn);
115120
if (anImport.getAlias() != null) {
116121
importAlias = anImport.getAlias();
117122
}
@@ -120,9 +125,13 @@ public J visitImport(J.Import anImport, ExecutionContext ctx) {
120125
return anImport;
121126
}
122127

123-
@Override
124-
public J visitCompilationUnit(J.CompilationUnit cu, ExecutionContext executionContext) {
125-
return super.visitCompilationUnit(cu, executionContext);
128+
private static boolean isWildcard(String fullName) {
129+
return fullName.matches(V1_SERVICE_MODEL_WILD_CARD_CLASS_PATTERN) ||
130+
fullName.matches(V1_SERVICE_WILD_CARD_CLASS_PATTERN);
131+
}
132+
133+
private static boolean isV1Class(JavaType.FullyQualified fullyQualified) {
134+
return isV1ModelClass(fullyQualified) || isV1ClientClass(fullyQualified);
126135
}
127136

128137
@Override
@@ -230,6 +239,23 @@ private J postVisitSourceFile(JavaSourceFile tree, ExecutionContext ctx, J curre
230239

231240
currentTree = sourceFile;
232241
}
242+
243+
return removeWildcardImports(ctx, currentTree, sourceFile);
244+
}
245+
246+
private J removeWildcardImports(ExecutionContext ctx, J currentTree, JavaSourceFile sourceFile) {
247+
for (String fqcn : wildcardImports) {
248+
sourceFile = (JavaSourceFile) new RemoveImport<ExecutionContext>(fqcn)
249+
.visit(sourceFile, ctx, getCursor().getParentOrThrow());
250+
251+
if (sourceFile != null) {
252+
sourceFile = sourceFile.withImports(
253+
ListUtils.map(sourceFile.getImports(), i -> visitAndCast(i, ctx,
254+
super::visitImport)));
255+
}
256+
257+
currentTree = sourceFile;
258+
}
233259
return currentTree;
234260
}
235261

@@ -281,33 +307,50 @@ public J visitFieldAccess(J.FieldAccess fieldAccess, ExecutionContext ctx) {
281307
public J visitIdentifier(J.Identifier ident, ExecutionContext ctx) {
282308

283309
JavaType currentType = ident.getType();
284-
if (currentType instanceof JavaType.FullyQualified) {
285-
JavaType.FullyQualified original = TypeUtils.asFullyQualified(currentType);
310+
if (!(currentType instanceof JavaType.FullyQualified)) {
311+
return visitAndCast(ident, ctx, super::visitIdentifier);
312+
}
313+
314+
JavaType.FullyQualified original = TypeUtils.asFullyQualified(currentType);
286315

287-
if (original != null && TypeUtils.isOfClassType(ident.getType(), original.getFullyQualifiedName())) {
288-
String fullyQualifiedName = original.getFullyQualifiedName();
316+
if (original != null && TypeUtils.isOfClassType(ident.getType(), original.getFullyQualifiedName())) {
317+
String fullyQualifiedName = original.getFullyQualifiedName();
289318

290-
if (oldTypeToNewType.containsKey(fullyQualifiedName)) {
291-
JavaType.Class originalType = oldTypeToNewType.get(fullyQualifiedName).left();
292-
String className = originalType.getClassName();
319+
if (isV1Class(original)) {
320+
storeV1ClassMetadata(fullyQualifiedName);
321+
JavaType.Class originalType = oldTypeToNewType.get(fullyQualifiedName).left();
322+
String className = originalType.getClassName();
293323

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-
}
324+
if (ident.getSimpleName().equals(className)) {
325+
JavaType targetType = oldTypeToNewType.get(fullyQualifiedName).right();
326+
ident = ident.withSimpleName(((JavaType.FullyQualified) targetType).getClassName());
327+
ident = ident.withType(updateType(currentType));
299328
}
300329
}
301330
}
302331

303332
return visitAndCast(ident, ctx, super::visitIdentifier);
304333
}
305334

335+
private void storeV1ClassMetadata(String currentFqcn) {
336+
JavaType.ShallowClass originalType = JavaType.ShallowClass.build(currentFqcn);
337+
String v2Equivalent = getV2Equivalent(currentFqcn);
338+
339+
JavaType targetType = JavaType.buildType(v2Equivalent);
340+
341+
oldTypeToNewType.put(currentFqcn, Pair.of(originalType, targetType));
342+
}
343+
306344
@Override
307345
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();
346+
JavaType.FullyQualified declaringType = method.getMethodType().getDeclaringType();
347+
if (isV1Class(declaringType)) {
348+
String fullyQualifiedName = declaringType.getFullyQualifiedName();
349+
storeV1ClassMetadata(fullyQualifiedName);
350+
351+
Pair<JavaType.Class, JavaType> oldTypeToNewTypePair = oldTypeToNewType.get(fullyQualifiedName);
352+
JavaType.Class originalType = oldTypeToNewTypePair.left();
353+
JavaType targetType = oldTypeToNewTypePair.right();
311354
if (method.getMethodType() != null && method.getMethodType().hasFlags(Flag.Static)) {
312355
if (method.getMethodType().getDeclaringType().isAssignableFrom(originalType)) {
313356
JavaSourceFile cu = getCursor().firstEnclosingOrThrow(JavaSourceFile.class);
@@ -329,6 +372,7 @@ public J visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx)
329372
}
330373
}
331374
}
375+
332376
return super.visitMethodInvocation(method, ctx);
333377
}
334378

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,12 @@ 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+
assertThat(NamingConversionUtils.getV2ModelPackageWildCardEquivalent("com.amazonaws.services.iot.*"))
87+
.isEqualTo("software.amazon.awssdk.services.iot.*");
88+
}
8189
}

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,40 @@ 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+
"import com.amazonaws.services.sqs.*;\n" +
82+
"class Test {\n" +
83+
" private DeleteQueueResult deleteQueResult;\n" +
84+
" static void method(CreateQueueResult createQueueResult) {\n" +
85+
" AmazonSQS sqs = null;\n" +
86+
" ListQueuesRequest request = null;\n" +
87+
" ListQueuesResult result = null;\n" +
88+
" InvalidAttributeNameException exception = null;\n" +
89+
" AmazonSQSException baseException = null;\n" +
90+
" }\n" +
91+
"}\n",
92+
"import software.amazon.awssdk.services.sqs.*;\n"
93+
+ "import software.amazon.awssdk.services.sqs.model.*;\n"
94+
+ "\n"
95+
+ "class Test {\n"
96+
+ " private DeleteQueueResponse deleteQueResult;\n"
97+
+ " static void method(CreateQueueResponse createQueueResult) {\n"
98+
+ " SqsClient sqs = null;\n"
99+
+ " ListQueuesRequest request = null;\n"
100+
+ " ListQueuesResponse result = null;\n"
101+
+ " InvalidAttributeNameException exception = null;\n"
102+
+ " SqsException baseException = null;\n"
103+
+ " }\n"
104+
+ "}"
105+
)
106+
);
107+
}
108+
75109
@Test
76110
@EnabledOnJre({JRE.JAVA_8})
77111
void shouldChangeFields() {

0 commit comments

Comments
 (0)