aboutsummaryrefslogtreecommitdiff
path: root/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeImpl.java
diff options
context:
space:
mode:
Diffstat (limited to 'javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeImpl.java')
-rw-r--r--javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeImpl.java211
1 files changed, 211 insertions, 0 deletions
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeImpl.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeImpl.java
new file mode 100644
index 000000000..927253e24
--- /dev/null
+++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/model/typesystem/ReferenceTypeImpl.java
@@ -0,0 +1,211 @@
+/*
+ * 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.symbolsolver.model.typesystem;
+
+import com.github.javaparser.resolution.MethodUsage;
+import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
+import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration;
+import com.github.javaparser.resolution.types.ResolvedReferenceType;
+import com.github.javaparser.resolution.types.ResolvedType;
+import com.github.javaparser.resolution.types.ResolvedTypeTransformer;
+import com.github.javaparser.resolution.types.ResolvedTypeVariable;
+import com.github.javaparser.resolution.types.parametrization.ResolvedTypeParametersMap;
+import com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder;
+import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeVariableDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * @author Federico Tomassetti
+ */
+// TODO Remove references to typeSolver: it is needed to instantiate other instances of ReferenceTypeUsage
+// and to get the Object type declaration
+public class ReferenceTypeImpl extends ResolvedReferenceType {
+
+ private TypeSolver typeSolver;
+
+ public static ResolvedReferenceType undeterminedParameters(ResolvedReferenceTypeDeclaration typeDeclaration, TypeSolver typeSolver) {
+ return new ReferenceTypeImpl(typeDeclaration, typeDeclaration.getTypeParameters().stream().map(
+ ResolvedTypeVariable::new
+ ).collect(Collectors.toList()), typeSolver);
+ }
+
+ @Override
+ protected ResolvedReferenceType create(ResolvedReferenceTypeDeclaration typeDeclaration, List<ResolvedType> typeParametersCorrected) {
+ return new ReferenceTypeImpl(typeDeclaration, typeParametersCorrected, typeSolver);
+ }
+
+ @Override
+ protected ResolvedReferenceType create(ResolvedReferenceTypeDeclaration typeDeclaration) {
+ return new ReferenceTypeImpl(typeDeclaration, typeSolver);
+ }
+
+ public ReferenceTypeImpl(ResolvedReferenceTypeDeclaration typeDeclaration, TypeSolver typeSolver) {
+ super(typeDeclaration);
+ this.typeSolver = typeSolver;
+ }
+
+ public ReferenceTypeImpl(ResolvedReferenceTypeDeclaration typeDeclaration, List<ResolvedType> typeArguments, TypeSolver typeSolver) {
+ super(typeDeclaration, typeArguments);
+ this.typeSolver = typeSolver;
+ }
+
+ @Override
+ public ResolvedTypeParameterDeclaration asTypeParameter() {
+ if (this.typeDeclaration instanceof JavaParserTypeVariableDeclaration) {
+ JavaParserTypeVariableDeclaration javaParserTypeVariableDeclaration = (JavaParserTypeVariableDeclaration) this.typeDeclaration;
+ return javaParserTypeVariableDeclaration.asTypeParameter();
+ }
+ throw new UnsupportedOperationException(this.typeDeclaration.getClass().getCanonicalName());
+ }
+
+ /**
+ * This method checks if ThisType t = new OtherType() would compile.
+ */
+ @Override
+ public boolean isAssignableBy(ResolvedType other) {
+ if (other instanceof NullType) {
+ return !this.isPrimitive();
+ }
+ // everything is assignable to Object except void
+ if (!other.isVoid() && this.getQualifiedName().equals(Object.class.getCanonicalName())) {
+ return true;
+ }
+ // consider boxing
+ if (other.isPrimitive()) {
+ if (this.getQualifiedName().equals(Object.class.getCanonicalName())) {
+ return true;
+ } else {
+ // Check if 'other' can be boxed to match this type
+ if (isCorrespondingBoxingType(other.describe())) return true;
+
+ // Resolve the boxed type and check if it can be assigned via widening reference conversion
+ SymbolReference<ResolvedReferenceTypeDeclaration> type = typeSolver.tryToSolveType(other.asPrimitive().getBoxTypeQName());
+ return type.getCorrespondingDeclaration().canBeAssignedTo(super.typeDeclaration);
+ }
+ }
+ if (other instanceof LambdaArgumentTypePlaceholder) {
+ return this.getTypeDeclaration().hasAnnotation(FunctionalInterface.class.getCanonicalName());
+ } else if (other instanceof ReferenceTypeImpl) {
+ ReferenceTypeImpl otherRef = (ReferenceTypeImpl) other;
+ if (compareConsideringTypeParameters(otherRef)) {
+ return true;
+ }
+ for (ResolvedReferenceType otherAncestor : otherRef.getAllAncestors()) {
+ if (compareConsideringTypeParameters(otherAncestor)) {
+ return true;
+ }
+ }
+ return false;
+ } else if (other.isTypeVariable()) {
+ for (ResolvedTypeParameterDeclaration.Bound bound : other.asTypeVariable().asTypeParameter().getBounds()) {
+ if (bound.isExtends()) {
+ if (this.isAssignableBy(bound.getType())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ } else if (other.isConstraint()){
+ return isAssignableBy(other.asConstraintType().getBound());
+ } else if (other.isWildcard()) {
+ if (this.getQualifiedName().equals(Object.class.getCanonicalName())) {
+ return true;
+ } else if (other.asWildcard().isExtends()) {
+ return isAssignableBy(other.asWildcard().getBoundedType());
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public Set<MethodUsage> getDeclaredMethods() {
+ // TODO replace variables
+ Set<MethodUsage> methods = new HashSet<>();
+ for (ResolvedMethodDeclaration methodDeclaration : getTypeDeclaration().getDeclaredMethods()) {
+ MethodUsage methodUsage = new MethodUsage(methodDeclaration);
+ methods.add(methodUsage);
+ }
+ return methods;
+ }
+
+ @Override
+ public ResolvedType toRawType() {
+ if (this.isRawType()) {
+ return this;
+ } else {
+ return new ReferenceTypeImpl(typeDeclaration, typeSolver);
+ }
+ }
+
+ @Override
+ public boolean mention(List<ResolvedTypeParameterDeclaration> typeParameters) {
+ return typeParametersValues().stream().anyMatch(tp -> tp.mention(typeParameters));
+ }
+
+ /**
+ * Execute a transformation on all the type parameters of this element.
+ */
+ @Override
+ public ResolvedType transformTypeParameters(ResolvedTypeTransformer transformer) {
+ ResolvedType result = this;
+ int i = 0;
+ for (ResolvedType tp : this.typeParametersValues()) {
+ ResolvedType transformedTp = transformer.transform(tp);
+ // Identity comparison on purpose
+ if (transformedTp != tp) {
+ List<ResolvedType> typeParametersCorrected = result.asReferenceType().typeParametersValues();
+ typeParametersCorrected.set(i, transformedTp);
+ result = create(typeDeclaration, typeParametersCorrected);
+ }
+ i++;
+ }
+ return result;
+ }
+
+ public List<ResolvedReferenceType> getAllAncestors() {
+ // We need to go through the inheritance line and propagate the type parametes
+
+ List<ResolvedReferenceType> 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());
+ ResolvedReferenceType objectRef = create(objectType);
+ ancestors.add(objectRef);
+ return ancestors;
+ }
+
+ public ResolvedReferenceType deriveTypeParameters(ResolvedTypeParametersMap typeParametersMap) {
+ return create(typeDeclaration, typeParametersMap);
+ }
+
+}