Skip to content

Commit b2235e8

Browse files
authored
refactor(ReferenceBuilder): Extract parameterized type reference creation into helpers (#3966)
1 parent 719cdc2 commit b2235e8

File tree

1 file changed

+65
-42
lines changed

1 file changed

+65
-42
lines changed

src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java

+65-42
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,10 @@
9090
import java.util.HashMap;
9191
import java.util.List;
9292
import java.util.Map;
93+
import java.util.Objects;
9394
import java.util.regex.Matcher;
9495
import java.util.regex.Pattern;
96+
import java.util.stream.Collectors;
9597

9698
import static spoon.support.compiler.jdt.JDTTreeBuilderQuery.searchPackage;
9799
import static spoon.support.compiler.jdt.JDTTreeBuilderQuery.searchType;
@@ -760,48 +762,7 @@ <T> CtTypeReference<T> getTypeReference(TypeBinding binding, boolean resolveGene
760762
if (binding instanceof RawTypeBinding) {
761763
ref = getTypeReference(((ParameterizedTypeBinding) binding).genericType());
762764
} else if (binding instanceof ParameterizedTypeBinding) {
763-
if (binding.actualType() != null && binding.actualType() instanceof LocalTypeBinding) {
764-
// When we define a nested class in a method and when the enclosing class of this method
765-
// is a parameterized type binding, JDT give a ParameterizedTypeBinding for the nested class
766-
// and hide the real class in actualType().
767-
ref = getTypeReference(binding.actualType());
768-
} else {
769-
ref = this.jdtTreeBuilder.getFactory().Core().createTypeReference();
770-
this.exploringParameterizedBindings.put(binding, ref);
771-
if (binding.isAnonymousType()) {
772-
ref.setSimpleName("");
773-
} else {
774-
ref.setSimpleName(String.valueOf(binding.sourceName()));
775-
if (binding.enclosingType() != null) {
776-
ref.setDeclaringType(getTypeReference(binding.enclosingType()));
777-
} else {
778-
ref.setPackage(getPackageReference(binding.getPackage()));
779-
}
780-
}
781-
}
782-
if (binding.actualType() instanceof MissingTypeBinding) {
783-
ref = getTypeReference(binding.actualType());
784-
}
785-
786-
if (((ParameterizedTypeBinding) binding).arguments != null) {
787-
for (TypeBinding b : ((ParameterizedTypeBinding) binding).arguments) {
788-
if (bindingCache.containsKey(b)) {
789-
ref.addActualTypeArgument(getCtCircularTypeReference(b));
790-
} else {
791-
if (!this.exploringParameterizedBindings.containsKey(b)) {
792-
this.exploringParameterizedBindings.put(b, null);
793-
CtTypeReference typeRefB = getTypeReference(b);
794-
this.exploringParameterizedBindings.put(b, typeRefB);
795-
ref.addActualTypeArgument(typeRefB);
796-
} else {
797-
CtTypeReference typeRefB = this.exploringParameterizedBindings.get(b);
798-
if (typeRefB != null) {
799-
ref.addActualTypeArgument(typeRefB.clone());
800-
}
801-
}
802-
}
803-
}
804-
}
765+
ref = getParameterizedTypeReference((ParameterizedTypeBinding) binding);
805766
} else if (binding instanceof MissingTypeBinding) {
806767
ref = this.jdtTreeBuilder.getFactory().Core().createTypeReference();
807768
ref.setSimpleName(new String(binding.sourceName()));
@@ -988,6 +949,68 @@ <T> CtTypeReference<T> getTypeReference(TypeBinding binding, boolean resolveGene
988949
return (CtTypeReference<T>) ref;
989950
}
990951

952+
/**
953+
* Create a parameterized type reference based on the provided binding.
954+
*/
955+
private CtTypeReference<?> getParameterizedTypeReference(ParameterizedTypeBinding binding) {
956+
CtTypeReference<?> ref;
957+
if (binding.actualType() instanceof LocalTypeBinding) {
958+
// When we define a nested class in a method and when the enclosing class of this method
959+
// is a parameterized type binding, JDT give a ParameterizedTypeBinding for the nested class
960+
// and hide the real class in actualType().
961+
ref = getTypeReference(binding.actualType());
962+
} else {
963+
ref = this.jdtTreeBuilder.getFactory().Core().createTypeReference();
964+
this.exploringParameterizedBindings.put(binding, ref);
965+
if (binding.isAnonymousType()) {
966+
ref.setSimpleName("");
967+
} else {
968+
ref.setSimpleName(String.valueOf(binding.sourceName()));
969+
if (binding.enclosingType() != null) {
970+
ref.setDeclaringType(getTypeReference(binding.enclosingType()));
971+
} else {
972+
ref.setPackage(getPackageReference(binding.getPackage()));
973+
}
974+
}
975+
}
976+
if (binding.actualType() instanceof MissingTypeBinding) {
977+
ref = getTypeReference(binding.actualType());
978+
}
979+
980+
getTypeArguments(binding).forEach(ref::addActualTypeArgument);
981+
return ref;
982+
}
983+
984+
/**
985+
* Get the type arguments from the binding, or an empty list if no type arguments can be found.
986+
*/
987+
private List<CtTypeReference<?>> getTypeArguments(ParameterizedTypeBinding binding) {
988+
return binding.arguments == null
989+
? Collections.emptyList()
990+
: Arrays.stream((binding.arguments))
991+
.map(this::getTypeReferenceFromTypeArgument)
992+
.filter(Objects::nonNull)
993+
.collect(Collectors.toList());
994+
}
995+
996+
/**
997+
* Get the type reference for a type argument binding. May return null when called recursively.
998+
*/
999+
private CtTypeReference<?> getTypeReferenceFromTypeArgument(TypeBinding typeArgBinding) {
1000+
if (bindingCache.containsKey(typeArgBinding)) {
1001+
return getCtCircularTypeReference(typeArgBinding);
1002+
} else if (exploringParameterizedBindings.containsKey(typeArgBinding)) {
1003+
// note: can be null if this method is called recursively
1004+
CtTypeReference<?> typeRefBeingExplored = exploringParameterizedBindings.get(typeArgBinding);
1005+
return typeRefBeingExplored == null ? null : typeRefBeingExplored.clone();
1006+
} else {
1007+
this.exploringParameterizedBindings.put(typeArgBinding, null);
1008+
CtTypeReference<?> typeRefB = getTypeReference(typeArgBinding);
1009+
this.exploringParameterizedBindings.put(typeArgBinding, typeRefB);
1010+
return typeRefB;
1011+
}
1012+
}
1013+
9911014
private CtTypeReference<?> getCtCircularTypeReference(TypeBinding b) {
9921015
return bindingCache.get(b).clone();
9931016
}

0 commit comments

Comments
 (0)