1 package com.github.javaparser.symbolsolver.resolution.typeinference;
2 
3 import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration;
4 import com.github.javaparser.resolution.types.ResolvedType;
5 
6 import java.util.LinkedList;
7 import java.util.List;
8 
9 /**
10  * Are meta-variables for types - that is, they are special names that allow abstract reasoning about types.
11  * To distinguish them from type variables, inference variables are represented with Greek letters, principally α.
12  *
13  * See JLS 18
14  *
15  * @author Federico Tomassetti
16  */
17 public class InferenceVariable implements ResolvedType {
18     private static int unnamedInstantiated = 0;
19 
20     private String name;
21     private ResolvedTypeParameterDeclaration typeParameterDeclaration;
22 
instantiate(List<ResolvedTypeParameterDeclaration> typeParameterDeclarations)23     public static List<InferenceVariable> instantiate(List<ResolvedTypeParameterDeclaration> typeParameterDeclarations) {
24         List<InferenceVariable> inferenceVariables = new LinkedList<>();
25         for (ResolvedTypeParameterDeclaration tp : typeParameterDeclarations) {
26             inferenceVariables.add(InferenceVariable.unnamed(tp));
27         }
28         return inferenceVariables;
29     }
30 
unnamed(ResolvedTypeParameterDeclaration typeParameterDeclaration)31     public static InferenceVariable unnamed(ResolvedTypeParameterDeclaration typeParameterDeclaration) {
32         return new InferenceVariable("__unnamed__" + (unnamedInstantiated++), typeParameterDeclaration);
33     }
34 
InferenceVariable(String name, ResolvedTypeParameterDeclaration typeParameterDeclaration)35     public InferenceVariable(String name, ResolvedTypeParameterDeclaration typeParameterDeclaration) {
36         this.name = name;
37         this.typeParameterDeclaration = typeParameterDeclaration;
38     }
39 
40     @Override
describe()41     public String describe() {
42         return name;
43     }
44 
45     @Override
equals(Object o)46     public boolean equals(Object o) {
47         if (this == o) return true;
48         if (o == null || getClass() != o.getClass()) return false;
49 
50         InferenceVariable that = (InferenceVariable) o;
51 
52         if (!name.equals(that.name)) return false;
53         return typeParameterDeclaration != null ? typeParameterDeclaration.equals(that.typeParameterDeclaration)
54                 : that.typeParameterDeclaration == null;
55     }
56 
57     @Override
hashCode()58     public int hashCode() {
59         int result = name.hashCode();
60         result = 31 * result + (typeParameterDeclaration != null ? typeParameterDeclaration.hashCode() : 0);
61         return result;
62     }
63 
64     @Override
isAssignableBy(ResolvedType other)65     public boolean isAssignableBy(ResolvedType other) {
66         if (other.equals(this)) {
67             return true;
68         }
69         throw new UnsupportedOperationException(
70                 "We are unable to determine the assignability of an inference variable without knowing the bounds and"
71                         + " constraints");
72     }
73 
getTypeParameterDeclaration()74     public ResolvedTypeParameterDeclaration getTypeParameterDeclaration() {
75         if (typeParameterDeclaration == null) {
76             throw new IllegalStateException("The type parameter declaration was not specified");
77         }
78         return typeParameterDeclaration;
79     }
80 
81     @Override
toString()82     public String toString() {
83         return "InferenceVariable{" +
84                 "name='" + name + '\'' +
85                 ", typeParameterDeclaration=" + typeParameterDeclaration +
86                 '}';
87     }
88 
89     @Override
mention(List<ResolvedTypeParameterDeclaration> typeParameters)90     public boolean mention(List<ResolvedTypeParameterDeclaration> typeParameters) {
91         return false;
92     }
93 }
94