|
90 | 90 | import java.util.HashMap;
|
91 | 91 | import java.util.List;
|
92 | 92 | import java.util.Map;
|
| 93 | +import java.util.Objects; |
93 | 94 | import java.util.regex.Matcher;
|
94 | 95 | import java.util.regex.Pattern;
|
| 96 | +import java.util.stream.Collectors; |
95 | 97 |
|
96 | 98 | import static spoon.support.compiler.jdt.JDTTreeBuilderQuery.searchPackage;
|
97 | 99 | import static spoon.support.compiler.jdt.JDTTreeBuilderQuery.searchType;
|
@@ -760,48 +762,7 @@ <T> CtTypeReference<T> getTypeReference(TypeBinding binding, boolean resolveGene
|
760 | 762 | if (binding instanceof RawTypeBinding) {
|
761 | 763 | ref = getTypeReference(((ParameterizedTypeBinding) binding).genericType());
|
762 | 764 | } 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); |
805 | 766 | } else if (binding instanceof MissingTypeBinding) {
|
806 | 767 | ref = this.jdtTreeBuilder.getFactory().Core().createTypeReference();
|
807 | 768 | ref.setSimpleName(new String(binding.sourceName()));
|
@@ -988,6 +949,68 @@ <T> CtTypeReference<T> getTypeReference(TypeBinding binding, boolean resolveGene
|
988 | 949 | return (CtTypeReference<T>) ref;
|
989 | 950 | }
|
990 | 951 |
|
| 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 | + |
991 | 1014 | private CtTypeReference<?> getCtCircularTypeReference(TypeBinding b) {
|
992 | 1015 | return bindingCache.get(b).clone();
|
993 | 1016 | }
|
|
0 commit comments