1f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassettipackage com.github.javaparser.symbolsolver.resolution.typeinference.constraintformulas; 2f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 3e8007447885c3ee0a462444cbc7fa83e80297f4aFederico Tomassettiimport com.github.javaparser.resolution.types.ResolvedType; 4f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassettiimport com.github.javaparser.symbolsolver.model.resolution.TypeSolver; 5f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassettiimport com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl; 6f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassettiimport com.github.javaparser.symbolsolver.resolution.typeinference.BoundSet; 7f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassettiimport com.github.javaparser.symbolsolver.resolution.typeinference.ConstraintFormula; 8f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassettiimport com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver; 9f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 10f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassettiimport static com.github.javaparser.symbolsolver.resolution.typeinference.TypeHelper.isCompatibleInALooseInvocationContext; 11f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassettiimport static com.github.javaparser.symbolsolver.resolution.typeinference.TypeHelper.isProperType; 12f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 13f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti/** 14f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti * A type S is compatible in a loose invocation context with type T 15f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti * 16f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti * @author Federico Tomassetti 17f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti */ 18f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassettipublic class TypeCompatibleWithType extends ConstraintFormula { 19e8007447885c3ee0a462444cbc7fa83e80297f4aFederico Tomassetti private ResolvedType s; 20e8007447885c3ee0a462444cbc7fa83e80297f4aFederico Tomassetti private ResolvedType t; 21f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti private TypeSolver typeSolver; 22f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 23e8007447885c3ee0a462444cbc7fa83e80297f4aFederico Tomassetti public TypeCompatibleWithType(TypeSolver typeSolver, ResolvedType s, ResolvedType t) { 24f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti this.typeSolver = typeSolver; 25f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti this.s = s; 26f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti this.t = t; 27f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti } 28f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 29f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti @Override 30f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti public ReductionResult reduce(BoundSet currentBoundSet) { 31f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti // A constraint formula of the form ‹S → T› is reduced as follows: 32f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti // 33f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti // 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. 34f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 35f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti if (isProperType(s) && isProperType(t)) { 36f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti if (isCompatibleInALooseInvocationContext(s, t)) { 37f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti return ReductionResult.trueResult(); 38f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti } else { 39f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti return ReductionResult.falseResult(); 40f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti } 41f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti } 42f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 43f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti // 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›. 44f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 45f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti if (s.isPrimitive()) { 46f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti ReflectionTypeSolver typeSolver = new ReflectionTypeSolver(); 47e8007447885c3ee0a462444cbc7fa83e80297f4aFederico Tomassetti ResolvedType sFirst = new ReferenceTypeImpl(typeSolver.solveType(s.asPrimitive().getBoxTypeQName()), typeSolver); 48f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti return ReductionResult.oneConstraint(new TypeCompatibleWithType(typeSolver, sFirst, t)); 49f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti } 50f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 51f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti // 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'›. 52f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 53f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti if (t.isPrimitive()) { 54f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti ReflectionTypeSolver typeSolver = new ReflectionTypeSolver(); 55e8007447885c3ee0a462444cbc7fa83e80297f4aFederico Tomassetti ResolvedType tFirst = new ReferenceTypeImpl(typeSolver.solveType(t.asPrimitive().getBoxTypeQName()), typeSolver); 56f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti return ReductionResult.oneConstraint(new TypeSameAsType(s, tFirst)); 57f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti } 58f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 59f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti // The fourth and fifth cases are implicit uses of unchecked conversion (§5.1.9). These, along with any use of 60f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti // unchecked conversion in the first case, may result in compile-time unchecked warnings, and may influence a 61f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti // method's invocation type (§15.12.2.6). 62f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 63f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti // 4. Otherwise, if T is a parameterized type of the form G<T1, ..., Tn>, and there exists no type of the 64f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti // form G<...> that is a supertype of S, but the raw type G is a supertype of S, then the constraint reduces 65f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti // to true. 66f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 67f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti if (t.isReferenceType() && !t.asReferenceType().getTypeDeclaration().getTypeParameters().isEmpty()) { 68f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti // FIXME I really cannot understand what the specification means... 69f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 70f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti // there exists a type of the form G<...> that is a supertype of S? 71f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti boolean condition1 = t.isAssignableBy(s); 72f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 73f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti // the raw type G is a supertype of S 74e8007447885c3ee0a462444cbc7fa83e80297f4aFederico Tomassetti ResolvedType G = t.asReferenceType().toRawType(); 75f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti boolean condition2 = G.isAssignableBy(s); 76f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 77f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti if (!condition1 && condition2) { 78f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti return ReductionResult.trueResult(); 79f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti } 80f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 81f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti //throw new UnsupportedOperationException(); 82f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti } 83f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 84f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti // 5. Otherwise, if T is an array type of the form G<T1, ..., Tn>[]k, and there exists no type of the form 85f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti // G<...>[]k that is a supertype of S, but the raw type G[]k is a supertype of S, then the constraint 86f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti // reduces to true. (The notation []k indicates an array type of k dimensions.) 87f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 88f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti if (t.isArray()) { 89f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti throw new UnsupportedOperationException(); 90f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti } 91f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 92f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti // 6. Otherwise, the constraint reduces to ‹S <: T› 93f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 94f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti return ReductionResult.empty().withConstraint(new TypeSubtypeOfType(typeSolver, s, t)); 95f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti } 96f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 97f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti @Override 98f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti public boolean equals(Object o) { 99f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti if (this == o) return true; 100f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti if (o == null || getClass() != o.getClass()) return false; 101f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 102f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti TypeCompatibleWithType that = (TypeCompatibleWithType) o; 103f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 104f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti if (!s.equals(that.s)) return false; 105f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti return t.equals(that.t); 106f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti } 107f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 108f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti @Override 109f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti public int hashCode() { 110f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti int result = s.hashCode(); 111f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti result = 31 * result + t.hashCode(); 112f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti return result; 113f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti } 114f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti 115f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti @Override 116f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti public String toString() { 117f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti return "TypeCompatibleWithType{" + 118f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti "s=" + s + 119f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti ", t=" + t + 120f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti '}'; 121f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti } 122f30c3694b1c6dd5b3db5dfbbc1dddcbffbf6cb95Federico Tomassetti} 123