diff options
Diffstat (limited to 'javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/TypeCompatibleWithType.java')
-rw-r--r-- | javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/TypeCompatibleWithType.java | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/TypeCompatibleWithType.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/TypeCompatibleWithType.java new file mode 100644 index 000000000..1c03064a8 --- /dev/null +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/resolution/typeinference/constraintformulas/TypeCompatibleWithType.java @@ -0,0 +1,122 @@ +package com.github.javaparser.symbolsolver.resolution.typeinference.constraintformulas; + +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl; +import com.github.javaparser.symbolsolver.resolution.typeinference.BoundSet; +import com.github.javaparser.symbolsolver.resolution.typeinference.ConstraintFormula; +import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver; + +import static com.github.javaparser.symbolsolver.resolution.typeinference.TypeHelper.isCompatibleInALooseInvocationContext; +import static com.github.javaparser.symbolsolver.resolution.typeinference.TypeHelper.isProperType; + +/** + * A type S is compatible in a loose invocation context with type T + * + * @author Federico Tomassetti + */ +public class TypeCompatibleWithType extends ConstraintFormula { + private ResolvedType s; + private ResolvedType t; + private TypeSolver typeSolver; + + public TypeCompatibleWithType(TypeSolver typeSolver, ResolvedType s, ResolvedType t) { + this.typeSolver = typeSolver; + this.s = s; + this.t = t; + } + + @Override + public ReductionResult reduce(BoundSet currentBoundSet) { + // A constraint formula of the form ‹S → T› is reduced as follows: + // + // 1. If S and T are proper types, the constraint reduces to true if S is compatible in a loose invocation context with T (§5.3), and false otherwise. + + if (isProperType(s) && isProperType(t)) { + if (isCompatibleInALooseInvocationContext(s, t)) { + return ReductionResult.trueResult(); + } else { + return ReductionResult.falseResult(); + } + } + + // 2. Otherwise, if S is a primitive type, let S' be the result of applying boxing conversion (§5.1.7) to S. Then the constraint reduces to ‹S' → T›. + + if (s.isPrimitive()) { + ReflectionTypeSolver typeSolver = new ReflectionTypeSolver(); + ResolvedType sFirst = new ReferenceTypeImpl(typeSolver.solveType(s.asPrimitive().getBoxTypeQName()), typeSolver); + return ReductionResult.oneConstraint(new TypeCompatibleWithType(typeSolver, sFirst, t)); + } + + // 3. Otherwise, if T is a primitive type, let T' be the result of applying boxing conversion (§5.1.7) to T. Then the constraint reduces to ‹S = T'›. + + if (t.isPrimitive()) { + ReflectionTypeSolver typeSolver = new ReflectionTypeSolver(); + ResolvedType tFirst = new ReferenceTypeImpl(typeSolver.solveType(t.asPrimitive().getBoxTypeQName()), typeSolver); + return ReductionResult.oneConstraint(new TypeSameAsType(s, tFirst)); + } + + // The fourth and fifth cases are implicit uses of unchecked conversion (§5.1.9). These, along with any use of + // unchecked conversion in the first case, may result in compile-time unchecked warnings, and may influence a + // method's invocation type (§15.12.2.6). + + // 4. Otherwise, if T is a parameterized type of the form G<T1, ..., Tn>, and there exists no type of the + // form G<...> that is a supertype of S, but the raw type G is a supertype of S, then the constraint reduces + // to true. + + if (t.isReferenceType() && !t.asReferenceType().getTypeDeclaration().getTypeParameters().isEmpty()) { + // FIXME I really cannot understand what the specification means... + + // there exists a type of the form G<...> that is a supertype of S? + boolean condition1 = t.isAssignableBy(s); + + // the raw type G is a supertype of S + ResolvedType G = t.asReferenceType().toRawType(); + boolean condition2 = G.isAssignableBy(s); + + if (!condition1 && condition2) { + return ReductionResult.trueResult(); + } + + //throw new UnsupportedOperationException(); + } + + // 5. Otherwise, if T is an array type of the form G<T1, ..., Tn>[]k, and there exists no type of the form + // G<...>[]k that is a supertype of S, but the raw type G[]k is a supertype of S, then the constraint + // reduces to true. (The notation []k indicates an array type of k dimensions.) + + if (t.isArray()) { + throw new UnsupportedOperationException(); + } + + // 6. Otherwise, the constraint reduces to ‹S <: T› + + return ReductionResult.empty().withConstraint(new TypeSubtypeOfType(typeSolver, s, t)); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + TypeCompatibleWithType that = (TypeCompatibleWithType) o; + + if (!s.equals(that.s)) return false; + return t.equals(that.t); + } + + @Override + public int hashCode() { + int result = s.hashCode(); + result = 31 * result + t.hashCode(); + return result; + } + + @Override + public String toString() { + return "TypeCompatibleWithType{" + + "s=" + s + + ", t=" + t + + '}'; + } +} |