diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedReferenceType.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedReferenceType.java index 182f2f74f8..340f233a85 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedReferenceType.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedReferenceType.java @@ -17,18 +17,13 @@ package com.github.javaparser.resolution.types; import com.github.javaparser.ast.type.ReferenceType; +import com.github.javaparser.resolution.MethodUsage; import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration; import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; +import com.github.javaparser.resolution.types.parametrization.ResolvedTypeParameterValueProvider; import com.github.javaparser.resolution.types.parametrization.ResolvedTypeParametersMap; import com.github.javaparser.resolution.types.parametrization.ResolvedTypeParametrized; -import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration; -import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration; -import com.github.javaparser.symbolsolver.model.methods.MethodUsage; -import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; -import com.github.javaparser.symbolsolver.model.typesystem.parametrization.TypeParameterValueProvider; -import com.github.javaparser.symbolsolver.model.typesystem.parametrization.TypeParametersMap; -import com.github.javaparser.symbolsolver.model.typesystem.parametrization.TypeParametrized; -import javaslang.Tuple2; +import com.github.javaparser.utils.Pair; import java.util.*; import java.util.stream.Collectors; @@ -53,14 +48,7 @@ public abstract class ResolvedReferenceType implements ResolvedType, // Constructors // - public ResolvedReferenceType(ResolvedReferenceTypeDeclaration typeDeclaration) { - this(typeDeclaration, deriveParams(typeDeclaration)); - } - - public ResolvedReferenceType(ResolvedReferenceTypeDeclaration typeDeclaration, List typeArguments, TypeSolver typeSolver) { - if (typeSolver == null) { - throw new IllegalArgumentException("typeSolver should not be null"); - } + public ResolvedReferenceType(ResolvedReferenceTypeDeclaration typeDeclaration, List typeArguments) { if (typeDeclaration.isTypeParameter()) { throw new IllegalArgumentException("You should use only Classes, Interfaces and enums"); } @@ -69,13 +57,12 @@ public ResolvedReferenceType(ResolvedReferenceTypeDeclaration typeDeclaration, L "expected either zero type arguments or has many as defined in the declaration (%d). Found %d", typeDeclaration.getTypeParameters().size(), typeArguments.size())); } - TypeParametersMap.Builder typeParametersMapBuilder = new TypeParametersMap.Builder(); + ResolvedTypeParametersMap.Builder typeParametersMapBuilder = new ResolvedTypeParametersMap.Builder(); for (int i = 0; i < typeArguments.size(); i++) { typeParametersMapBuilder.setValue(typeDeclaration.getTypeParameters().get(i), typeArguments.get(i)); } this.typeParametersMap = typeParametersMapBuilder.build(); this.typeDeclaration = typeDeclaration; - this.typeSolver = typeSolver; } // @@ -87,7 +74,7 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - ReferenceType that = (ReferenceType) o; + ResolvedReferenceType that = (ResolvedReferenceType) o; if (!typeDeclaration.equals(that.typeDeclaration)) return false; if (!typeParametersMap.equals(that.typeParametersMap)) return false; @@ -156,57 +143,7 @@ public String describe() { /** * Execute a transformation on all the type parameters of this element. */ - public Type transformTypeParameters(TypeTransformer transformer) { - Type result = this; - int i = 0; - for (Type tp : this.typeParametersValues()) { - Type transformedTp = transformer.transform(tp); - // Identity comparison on purpose - if (transformedTp != tp) { - List typeParametersCorrected = result.asReferenceType().typeParametersValues(); - typeParametersCorrected.set(i, transformedTp); - result = create(typeDeclaration, typeParametersCorrected, typeSolver); - } - i++; - } - return result; - } - - @Override - public ResolvedType replaceTypeVariables(ResolvedTypeParameterDeclaration tpToReplace, - ResolvedType replaced, - Map inferredTypes) { - if (replaced == null) { - throw new IllegalArgumentException(); - } - - ReferenceType result = this; - int i = 0; - for (ResolvedType tp : this.typeParametersValues()) { - ResolvedType transformedTp = tp.replaceTypeVariables(tpToReplace, replaced, inferredTypes); - // Identity comparison on purpose - if (tp.isTypeVariable() && tp.asTypeVariable().describe().equals(tpToReplace.getName())) { - inferredTypes.put(tp.asTypeParameter(), replaced); - } - // FIXME - if (true) { - List typeParametersCorrected = result.asReferenceType().typeParametersValues(); - typeParametersCorrected.set(i, transformedTp); - result = create(typeDeclaration, typeParametersCorrected, typeSolver); - } - i++; - } - - List values = result.typeParametersValues(); - // FIXME - if(values.contains(tpToReplace)){ - int index = values.indexOf(tpToReplace); - values.set(index, replaced); - return create(result.getTypeDeclaration(), values, typeSolver); - } - - return result; - } + public abstract ResolvedType transformTypeParameters(ResolvedTypeTransformer transformer); /// /// Assignability @@ -235,22 +172,7 @@ public ResolvedType replaceTypeVariables(ResolvedTypeParameterDeclaration tpToRe * a call to getAllAncestors on a reference to Bar having type parameter Boolean should include * Foo<Boolean, String>. */ - public List getAllAncestors() { - // We need to go through the inheritance line and propagate the type parametes - - List ancestors = typeDeclaration.getAllAncestors(); - - ancestors = ancestors.stream() - .map(a -> typeParametersMap().replaceAll(a).asReferenceType()) - .collect(Collectors.toList()); - - // Avoid repetitions of Object - ancestors.removeIf(a -> a.getQualifiedName().equals(Object.class.getCanonicalName())); - ResolvedReferenceTypeDeclaration objectType = typeSolver.solveType(Object.class.getCanonicalName()); - ReferenceType objectRef = create(objectType, typeSolver); - ancestors.add(objectRef); - return ancestors; - } + public abstract List getAllAncestors(); public final List getAllInterfacesAncestors() { return getAllAncestors().stream() @@ -272,7 +194,7 @@ public final List getAllClassesAncestors() { * Get the type associated with the type parameter with the given name. * It returns Optional.empty unless the type declaration declares a type parameter with the given name. */ - public Optional getGenericParameterByName(String name) { + public Optional getGenericParameterByName(String name) { for (ResolvedTypeParameterDeclaration tp : typeDeclaration.getTypeParameters()) { if (tp.getName().equals(name)) { return Optional.of(this.typeParametersMap().getValue(tp)); @@ -293,11 +215,11 @@ public List typeParametersValues() { * Get the values for all type parameters declared on this type. * In case of raw types the values correspond to TypeVariables. */ - public List> getTypeParametersMap() { - List> typeParametersMap = new ArrayList<>(); + public List> getTypeParametersMap() { + List> typeParametersMap = new ArrayList<>(); if (!isRawType()) { for (int i = 0; i < typeDeclaration.getTypeParameters().size(); i++) { - typeParametersMap.add(new Tuple2<>(typeDeclaration.getTypeParameters().get(0), typeParametersValues().get(i))); + typeParametersMap.add(new Pair<>(typeDeclaration.getTypeParameters().get(0), typeParametersValues().get(i))); } } return typeParametersMap; @@ -364,7 +286,7 @@ public boolean isRawType() { return true; } for (String name : typeParametersMap().getNames()) { - Optional value = typeParametersMap().getValueBySignature(name); + Optional value = typeParametersMap().getValueBySignature(name); if (value.isPresent() && value.get().isTypeVariable() && value.get().asTypeVariable().qualifiedName().equals(name)) { // nothing to do } else { @@ -376,7 +298,7 @@ public boolean isRawType() { return false; } - public Optional typeParamValue(TypeParameterDeclaration typeParameterDeclaration) { + public Optional typeParamValue(ResolvedTypeParameterDeclaration typeParameterDeclaration) { if (typeParameterDeclaration.declaredOnMethod()) { throw new IllegalArgumentException(); } @@ -384,7 +306,7 @@ public Optional typeParamValue(TypeParameterDeclaration typeParameterDecla if (typeId.equals(typeParameterDeclaration.getContainerId())) { return Optional.of(this.typeParametersMap().getValue(typeParameterDeclaration)); } - for (ReferenceType ancestor : this.getAllAncestors()) { + for (ResolvedReferenceType ancestor : this.getAllAncestors()) { if (ancestor.getId().equals(typeParameterDeclaration.getContainerId())) { return Optional.of(ancestor.typeParametersMap().getValue(typeParameterDeclaration)); } @@ -392,21 +314,21 @@ public Optional typeParamValue(TypeParameterDeclaration typeParameterDecla return Optional.empty(); } - public abstract Type toRawType(); + public abstract ResolvedType toRawType(); // // Protected methods // - protected abstract ReferenceType create(ReferenceTypeDeclaration typeDeclaration, List typeParameters, TypeSolver typeSolver); + protected abstract ReferenceType create(ResolvedReferenceTypeDeclaration typeDeclaration, List typeParameters); - protected ReferenceType create(ReferenceTypeDeclaration typeDeclaration, TypeParametersMap typeParametersMap, TypeSolver typeSolver) { + protected ReferenceType create(ResolvedReferenceTypeDeclaration typeDeclaration, ResolvedTypeParametersMap typeParametersMap) { return create(typeDeclaration, typeDeclaration.getTypeParameters().stream() .map(typeParametersMap::getValue) - .collect(Collectors.toList()), typeSolver); + .collect(Collectors.toList())); } - protected abstract ReferenceType create(ReferenceTypeDeclaration typeDeclaration, TypeSolver typeSolver); + protected abstract ReferenceType create(ResolvedReferenceTypeDeclaration typeDeclaration); protected boolean isCorrespondingBoxingType(String typeName) { switch (typeName) { @@ -431,7 +353,7 @@ protected boolean isCorrespondingBoxingType(String typeName) { } } - protected boolean compareConsideringTypeParameters(ReferenceType other) { + protected boolean compareConsideringTypeParameters(ResolvedReferenceType other) { if (other.equals(this)) { return true; } @@ -443,11 +365,11 @@ protected boolean compareConsideringTypeParameters(ReferenceType other) { throw new IllegalStateException(); } for (int i = 0; i < typeParametersValues().size(); i++) { - Type thisParam = typeParametersValues().get(i); - Type otherParam = other.typeParametersValues().get(i); + ResolvedType thisParam = typeParametersValues().get(i); + ResolvedType otherParam = other.typeParametersValues().get(i); if (!thisParam.equals(otherParam)) { - if (thisParam instanceof Wildcard) { - Wildcard thisParamAsWildcard = (Wildcard) thisParam; + if (thisParam instanceof ResolvedWildcard) { + ResolvedWildcard thisParamAsWildcard = (ResolvedWildcard) thisParam; if (thisParamAsWildcard.isSuper() && otherParam.isAssignableBy(thisParamAsWildcard.getBoundedType())) { // ok } else if (thisParamAsWildcard.isExtends() && thisParamAsWildcard.getBoundedType().isAssignableBy(otherParam)) { @@ -458,9 +380,9 @@ protected boolean compareConsideringTypeParameters(ReferenceType other) { return false; } } else { - if (thisParam instanceof TypeVariable && otherParam instanceof TypeVariable) { - List thisBounds = thisParam.asTypeVariable().asTypeParameter().getBounds(this.typeSolver).stream().map(bound -> bound.getType()).collect(Collectors.toList()); - List otherBounds = otherParam.asTypeVariable().asTypeParameter().getBounds(other.typeSolver).stream().map(bound -> bound.getType()).collect(Collectors.toList()); + if (thisParam instanceof ResolvedTypeVariable && otherParam instanceof ResolvedTypeVariable) { + List thisBounds = thisParam.asTypeVariable().asTypeParameter().getBounds().stream().map(bound -> bound.getType()).collect(Collectors.toList()); + List otherBounds = otherParam.asTypeVariable().asTypeParameter().getBounds().stream().map(bound -> bound.getType()).collect(Collectors.toList()); if (thisBounds.size() == otherBounds.size() && otherBounds.containsAll(thisBounds)) { return true; } @@ -478,11 +400,9 @@ protected boolean compareConsideringTypeParameters(ReferenceType other) { // Private methods // - private static List deriveParams(ReferenceTypeDeclaration typeDeclaration) { - return typeDeclaration.getTypeParameters().stream().map((tp) -> new TypeVariable(tp)).collect(Collectors.toList()); + private static List deriveParams(ResolvedReferenceTypeDeclaration typeDeclaration) { + return typeDeclaration.getTypeParameters().stream().map((tp) -> new ResolvedTypeVariable(tp)).collect(Collectors.toList()); } - public ReferenceType deriveTypeParameters(ResolvedTypeParametersMap typeParametersMap) { - return create(typeDeclaration, typeParametersMap, typeSolver); - } + public abstract ReferenceType deriveTypeParameters(ResolvedTypeParametersMap typeParametersMap); } diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedTypeTransformer.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedTypeTransformer.java new file mode 100644 index 0000000000..89384e7a07 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedTypeTransformer.java @@ -0,0 +1,25 @@ +/* + * Copyright 2016 Federico Tomassetti + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.github.javaparser.resolution.types; + +/** + * @author Federico Tomassetti + */ +@FunctionalInterface +public interface ResolvedTypeTransformer { + ResolvedType transform(ResolvedType type); +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedTypeVariable.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedTypeVariable.java index 98bf97b23d..18b23ad211 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedTypeVariable.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedTypeVariable.java @@ -17,7 +17,6 @@ package com.github.javaparser.resolution.types; import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; -import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration; import java.util.List; import java.util.Map; diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParameterValueProvider.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParameterValueProvider.java new file mode 100644 index 0000000000..54dfab70a6 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParameterValueProvider.java @@ -0,0 +1,51 @@ +package com.github.javaparser.resolution.types.parametrization; + +import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.resolution.types.ResolvedWildcard; + +import java.util.Optional; + +/** + * @author Federico Tomassetti + */ +public interface ResolvedTypeParameterValueProvider { + + /** + * Calculate the value for the given type parameter. + * It could be inherited. + */ + Optional typeParamValue(ResolvedTypeParameterDeclaration typeParameterDeclaration); + + /** + * Replace the type typeParametersValues present in the given type with the ones for which this type + * has a value. + */ + default ResolvedType useThisTypeParametersOnTheGivenType(ResolvedType type) { + if (type.isTypeVariable()) { + ResolvedTypeParameterDeclaration typeParameter = type.asTypeParameter(); + if (typeParameter.declaredOnType()) { + Optional typeParam = typeParamValue(typeParameter); + if (typeParam.isPresent()) { + type = typeParam.get(); + } + } + } + + if (type.isWildcard() && type.asWildcard().isBounded()) { + if (type.asWildcard().isExtends()) { + return ResolvedWildcard.extendsBound(useThisTypeParametersOnTheGivenType(type.asWildcard().getBoundedType())); + } else { + return ResolvedWildcard.superBound(useThisTypeParametersOnTheGivenType(type.asWildcard().getBoundedType())); + } + } + + if (type.isReferenceType()) { + type = type.asReferenceType().transformTypeParameters(this::useThisTypeParametersOnTheGivenType); + } + + return type; + } + + Optional getGenericParameterByName(String name); +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParametersMap.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParametersMap.java index a901d39bfa..07b54f7b98 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParametersMap.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/parametrization/ResolvedTypeParametersMap.java @@ -38,7 +38,8 @@ public Builder() { nameToDeclaration = new HashMap<>(); } - private Builder(Map nameToValue, Map nameToDeclaration) { + private Builder(Map nameToValue, + Map nameToDeclaration) { this.nameToValue = new HashMap<>(); this.nameToValue.putAll(nameToValue); this.nameToDeclaration = new HashMap<>(); @@ -49,7 +50,8 @@ public ResolvedTypeParametersMap build() { return new ResolvedTypeParametersMap(nameToValue, nameToDeclaration); } - public Builder setValue(ResolvedTypeParameterDeclaration typeParameter, ResolvedType value) { + public Builder setValue(ResolvedTypeParameterDeclaration typeParameter, + ResolvedType value) { // TODO: we shouldn't just silently overwrite existing types! String qualifiedName = typeParameter.getQualifiedName(); nameToValue.put(qualifiedName, value); @@ -88,7 +90,8 @@ public static ResolvedTypeParametersMap empty() { return new Builder().build(); } - private ResolvedTypeParametersMap(Map nameToValue, Map nameToDeclaration) { + private ResolvedTypeParametersMap(Map nameToValue, + Map nameToDeclaration) { this.nameToValue = new HashMap<>(); this.nameToValue.putAll(nameToValue); this.nameToDeclaration = new HashMap<>();