Description

This commit is contained in:
Dmitri Boulytchev
2005-02-02 22:58:37 +03:00
parent 63f8af95f8
commit c654ef5ad8
10 changed files with 550 additions and 358 deletions
@@ -172,32 +172,4 @@ public class GenericsUtil {
return type.getInternalCanonicalText().equals(type.getCanonicalText());
}
public static PsiClass[] getGreatestLowerClasses(final PsiClass aClass, final PsiClass bClass) {
if (InheritanceUtil.isInheritorOrSelf(aClass, bClass, true)) {
return new PsiClass[]{aClass};
}
if (InheritanceUtil.isInheritorOrSelf(bClass, aClass, true)) {
return new PsiClass[]{bClass};
}
final Set<PsiClass> descendants = new LinkedHashSet<PsiClass>();
new Object() {
public void getGreatestLowerClasses(final PsiClass aClass, final PsiClass bClass, final Set<PsiClass> descendants) {
if (aClass.isInheritor(bClass, true)) {
descendants.add(bClass);
}
else {
final PsiSearchHelper helper = aClass.getManager().getSearchHelper();
final PsiClass[] bSubs = helper.findInheritors(bClass, helper.getUseScope(bClass), true);
for (int i = 0; i < bSubs.length; i++) {
getLeastUpperClassesInner(bSubs[i], aClass, descendants);
}
}
}
}.getGreatestLowerClasses(aClass, bClass, descendants);
return descendants.toArray(new PsiClass[descendants.size()]);
}
}
@@ -78,6 +78,10 @@ public class System {
final PsiElement element = i.next();
final PsiType type = myTypes.get(element);
if (type == null){
continue;
}
if (element instanceof PsiParameter) {
final PsiParameter parm = (PsiParameter)element;
final PsiMethod method = (PsiMethod)parm.getDeclarationScope();
@@ -429,7 +433,11 @@ public class System {
for (final Iterator<PsiElement> e = myElements.iterator(); e.hasNext();) {
final PsiElement element = e.next();
data[i++] = binding.substitute(myTypes.get(element)).getCanonicalText() + "\\n" + elementString(element);
final PsiType t = myTypes.get(element);
if (t != null)
data[i++] = binding.substitute(t).getCanonicalText() + "\\n" + elementString(element);
else
data[i++] = "\\n" + elementString(element);
}
Arrays.sort(data,
@@ -33,6 +33,7 @@ public class SystemBuilder {
private PsiManager myManager;
private HashMap<PsiElement, Boolean> myMethodCache;
private HashMap<PsiParameter, PsiParameter> myParameters;
private HashMap<PsiMethod, PsiMethod> myMethods;
private HashMap<PsiMethod, PsiMethod> mySuper;
private HashMap<PsiElement, PsiType> myTypes;
private HashSet<PsiAnchor> myVisitedConstructions;
@@ -46,6 +47,7 @@ public class SystemBuilder {
mySettings = settings;
myMethodCache = new HashMap<PsiElement, Boolean>();
myParameters = new HashMap<PsiParameter, PsiParameter>();
myMethods = new HashMap<PsiMethod, PsiMethod>();
mySuper = new HashMap<PsiMethod, PsiMethod>();
myTypes = new HashMap<PsiElement, PsiType>();
myVisitedConstructions = new HashSet<PsiAnchor>();
@@ -95,16 +97,25 @@ public class SystemBuilder {
keyMethod = superMethod;
myMethods.put(method, keyMethod);
if (parameter != null) {
keyParameter = (PsiParameter)e;
myParameters.put(parameter, keyParameter);
}
}
else {
Boolean good = myMethodCache.get(method);
if (good != null) {
return good.booleanValue();
if (good != null && good.booleanValue()) {
if (myMethods.get(method) == null) {
myMethods.put(method, method);
}
if (parameter != null && myParameters.get(parameter) == null) {
myParameters.put(parameter, parameter);
}
return true;
}
keyMethod = method;
@@ -112,29 +123,35 @@ public class SystemBuilder {
}
final PsiMethod[] overriders = helper.findOverridingMethods(keyMethod, keyMethod.getUseScope(), true);
PsiMethod prev = keyMethod;
for (int i = 0; i < overriders.length; i++) {
PsiMethod overrider = overriders[i];
if (prev != null) {
mySuper.put(overrider, prev);
prev = overrider;
}
PsiElement e =
parameter == null ? (PsiElement)overrider : overrider.getParameterList().getParameters()[index];
final PsiMethod overrider = overriders[i];
final PsiElement e = parameter == null ? (PsiElement)overrider : overrider.getParameterList().getParameters()[index];
if (!victims.contains(e)) {
myMethodCache.put(keyMethod, new Boolean(false));
return false;
}
}
for (int i = 0; i < overriders.length; i++) {
final PsiMethod overrider = overriders[i];
final PsiElement e = parameter == null ? (PsiElement)overrider : overrider.getParameterList().getParameters()[index];
mySuper.put(overrider, keyMethod);
myMethods.put(overrider, keyMethod);
if (parameter != null) {
myParameters.put(parameter, keyParameter);
myParameters.put((PsiParameter)e, keyParameter);
}
}
myMethods.put(method, keyMethod);
if (parameter != null) {
myParameters.put(parameter, keyParameter);
}
myMethodCache.put(keyMethod, new Boolean(true));
return true;
@@ -279,100 +296,106 @@ public class SystemBuilder {
}
else {
final PsiType theType =
new Object() {
PsiType introduceAdditionalTypeVariables(final PsiType type,
final PsiSubstitutor qualifier,
final PsiSubstitutor supertype) {
final PsiClassType.ClassResolveResult result = Util.resolveType(type);
final PsiClass aClass = result.getElement();
new Object() {
PsiType introduceAdditionalTypeVariables(final PsiType type,
final PsiSubstitutor qualifier,
final PsiSubstitutor supertype) {
final PsiClassType.ClassResolveResult result = Util.resolveType(type);
final PsiClass aClass = result.getElement();
if (aClass != null) {
if (aClass instanceof PsiTypeParameter) {
final PsiTypeParameter tp = ((PsiTypeParameter)aClass);
if (aClass != null) {
if (aClass instanceof PsiTypeParameter) {
final PsiTypeParameter tp = ((PsiTypeParameter)aClass);
final PsiClassType[] extypes = tp.getExtendsListTypes();
PsiType pv = mapping.get(tp);
PsiType pv = mapping.get(tp);
if (pv == null) {
pv = myTypeVariableFactory.create();
mapping.put(tp, pv);
}
return pv;
if (pv == null) {
pv = myTypeVariableFactory.create();
mapping.put(tp, pv);
}
final Map<PsiTypeParameter, PsiType> substitutionMap = result.getSubstitutor().getSubstitutionMap();
PsiSubstitutor theSubst = PsiSubstitutor.EMPTY;
for (Iterator<PsiTypeParameter> t = substitutionMap.keySet().iterator(); t.hasNext();) {
final PsiTypeParameter p = t.next();
final PsiType pType = substitutionMap.get(p);
if (pType instanceof PsiWildcardType) {
final PsiWildcardType wildcard = ((PsiWildcardType)pType);
final PsiType theBound = wildcard.getBound();
if (theBound != null) {
final PsiType bound = Util.substituteType(Util.substituteType(theBound, supertype), qualifier);
if (Util.bindsTypeVariables(bound)) {
final PsiType var = myTypeVariableFactory.create();
if (wildcard.isExtends()) {
system.addSubtypeConstraint(bound, var);
}
else {
system.addSubtypeConstraint(var, bound);
}
theSubst = theSubst.put(p, var);
}
else if (Util.bindsTypeParameters(bound, typeParameters)) {
final PsiType var = myTypeVariableFactory.create();
PsiSubstitutor subst = PsiSubstitutor.EMPTY;
for (int i = 0; i < aTypeParms.length; i++) {
final PsiTypeParameter aTypeParm = aTypeParms[i];
PsiType parmVar = mapping.get(aTypeParm);
if (parmVar == null) {
parmVar = myTypeVariableFactory.create();
mapping.put(aTypeParm, parmVar);
}
subst = subst.put(aTypeParm, parmVar);
}
final PsiType bnd = Util.substituteType(bound, subst);
if (wildcard.isExtends()) {
system.addSubtypeConstraint(bnd, var);
}
else {
system.addSubtypeConstraint(var, bnd);
}
theSubst = theSubst.put(p, var);
}
else {
theSubst = theSubst.put(p, pType);
}
}
}
else {
theSubst = theSubst.put(p, introduceAdditionalTypeVariables(pType, qualifier, supertype));
}
for (int j = 0; j < extypes.length; j++) {
final PsiType extype = Util.substituteType(extypes[j], qualifier);
system.addSubtypeConstraint(pv, extype);
}
return aClass.getManager().getElementFactory().createType(aClass, theSubst);
return pv;
}
return type;
final Map<PsiTypeParameter, PsiType> substitutionMap = result.getSubstitutor().getSubstitutionMap();
PsiSubstitutor theSubst = PsiSubstitutor.EMPTY;
for (Iterator<PsiTypeParameter> t = substitutionMap.keySet().iterator(); t.hasNext();) {
final PsiTypeParameter p = t.next();
final PsiType pType = substitutionMap.get(p);
if (pType instanceof PsiWildcardType) {
final PsiWildcardType wildcard = ((PsiWildcardType)pType);
final PsiType theBound = wildcard.getBound();
if (theBound != null) {
final PsiType bound = Util.substituteType(Util.substituteType(theBound, supertype), qualifier);
if (Util.bindsTypeVariables(bound)) {
final PsiType var = myTypeVariableFactory.create();
if (wildcard.isExtends()) {
system.addSubtypeConstraint(bound, var);
}
else {
system.addSubtypeConstraint(var, bound);
}
theSubst = theSubst.put(p, var);
}
else if (Util.bindsTypeParameters(bound, typeParameters)) {
final PsiType var = myTypeVariableFactory.create();
PsiSubstitutor subst = PsiSubstitutor.EMPTY;
for (int i = 0; i < aTypeParms.length; i++) {
final PsiTypeParameter aTypeParm = aTypeParms[i];
PsiType parmVar = mapping.get(aTypeParm);
if (parmVar == null) {
parmVar = myTypeVariableFactory.create();
mapping.put(aTypeParm, parmVar);
}
subst = subst.put(aTypeParm, parmVar);
}
final PsiType bnd = Util.substituteType(bound, subst);
if (wildcard.isExtends()) {
system.addSubtypeConstraint(bnd, var);
}
else {
system.addSubtypeConstraint(var, bnd);
}
theSubst = theSubst.put(p, var);
}
else {
theSubst = theSubst.put(p, pType);
}
}
}
else {
theSubst = theSubst.put(p, introduceAdditionalTypeVariables(pType, qualifier, supertype));
}
}
return aClass.getManager().getElementFactory().createType(aClass, theSubst);
}
}.introduceAdditionalTypeVariables(
Util.substituteType(Util.substituteType(parmType, supertypeSubstitutor), qualifierSubstitutor), qualifierSubstitutor,
supertypeSubstitutor);
return type;
}
}.introduceAdditionalTypeVariables(
Util.substituteType(Util.substituteType(parmType, supertypeSubstitutor), qualifierSubstitutor), qualifierSubstitutor,
supertypeSubstitutor);
system.addSubtypeConstraint(argumenType, theType);
}
@@ -575,6 +598,24 @@ public class SystemBuilder {
}
return;
}
else if (element instanceof PsiMethod) {
final PsiType reType = getType(element);
element.accept(new PsiRecursiveElementVisitor() {
public void visitReturnStatement(final PsiReturnStatement statement) {
super.visitReturnStatement(statement);
final PsiExpression retExpr = statement.getReturnValue();
if (retExpr != null) {
system.addSubtypeConstraint(e.valuateType(retExpr), reType);
}
}
}
);
return;
}
final PsiStatement root = (PsiStatement)PsiTreeUtil.getParentOfType(element, PsiStatement.class);
@@ -583,63 +624,65 @@ public class SystemBuilder {
if (!myVisitedConstructions.contains(anchor)) {
root.accept(new PsiRecursiveElementVisitor() {
public void visitAssignmentExpression(final PsiAssignmentExpression expression) {
super.visitAssignmentExpression(expression);
public void visitAssignmentExpression(final PsiAssignmentExpression expression) {
super.visitAssignmentExpression(expression);
system.addSubtypeConstraint(e.valuateType(expression.getRExpression()), e.valuateType(expression.getLExpression()));
}
system.addSubtypeConstraint(e.valuateType(expression.getRExpression()), e.valuateType(expression.getLExpression()));
}
public void visitConditionalExpression(final PsiConditionalExpression expression) {
super.visitConditionalExpression(expression);
public void visitConditionalExpression(final PsiConditionalExpression expression) {
super.visitConditionalExpression(expression);
system.addSubtypeConstraint(e.valuateType(expression.getThenExpression()), e.valuateType(expression.getElseExpression()));
system.addSubtypeConstraint(e.valuateType(expression.getElseExpression()), e.valuateType(expression.getThenExpression()));
}
system.addSubtypeConstraint(e.valuateType(expression.getThenExpression()),
e.valuateType(expression.getElseExpression()));
system.addSubtypeConstraint(e.valuateType(expression.getElseExpression()),
e.valuateType(expression.getThenExpression()));
}
public void visitMethodCallExpression(final PsiMethodCallExpression expression) {
super.visitMethodCallExpression(expression);
e.valuateType(expression);
}
public void visitMethodCallExpression(final PsiMethodCallExpression expression) {
super.visitMethodCallExpression(expression);
e.valuateType(expression);
}
public void visitReturnStatement(final PsiReturnStatement statement) {
super.visitReturnStatement(statement);
public void visitReturnStatement(final PsiReturnStatement statement) {
super.visitReturnStatement(statement);
final PsiMethod method = PsiTreeUtil.getParentOfType(statement, PsiMethod.class);
final PsiMethod method = PsiTreeUtil.getParentOfType(statement, PsiMethod.class);
if (method != null) {
system.addSubtypeConstraint(e.valuateType(statement.getReturnValue()), getType(method));
}
}
if (method != null) {
system.addSubtypeConstraint(e.valuateType(statement.getReturnValue()), getType(method));
}
}
public void visitTypeCastExpression(final PsiTypeCastExpression expression) {
super.visitTypeCastExpression(expression);
public void visitTypeCastExpression(final PsiTypeCastExpression expression) {
super.visitTypeCastExpression(expression);
system.addSubtypeConstraint(e.valuateType(expression.getOperand()), e.valuateType(expression));
}
system.addSubtypeConstraint(e.valuateType(expression.getOperand()), e.valuateType(expression));
}
public void visitNewExpression(final PsiNewExpression expression) {
super.visitNewExpression(expression);
public void visitNewExpression(final PsiNewExpression expression) {
super.visitNewExpression(expression);
final PsiArrayInitializerExpression init = expression.getArrayInitializer();
final PsiArrayInitializerExpression init = expression.getArrayInitializer();
if (init != null) {
final PsiExpression[] inits = init.getInitializers();
final PsiType type = getType(expression);
if (init != null) {
final PsiExpression[] inits = init.getInitializers();
final PsiType type = getType(expression);
for (int i = 0; i < inits.length; i++) {
system.addSubtypeConstraint(e.valuateType(inits[i]).createArrayType(), type);
}
}
}
for (int i = 0; i < inits.length; i++) {
system.addSubtypeConstraint(e.valuateType(inits[i]).createArrayType(), type);
}
}
}
public void visitReferenceExpression(final PsiReferenceExpression expression) {
final PsiExpression qualifierExpression = expression.getQualifierExpression();
public void visitReferenceExpression(final PsiReferenceExpression expression) {
final PsiExpression qualifierExpression = expression.getQualifierExpression();
if (qualifierExpression != null) {
qualifierExpression.accept(this);
}
}
});
if (qualifierExpression != null) {
qualifierExpression.accept(this);
}
}
});
myVisitedConstructions.add(anchor);
}
@@ -673,47 +716,47 @@ public class SystemBuilder {
if (definedType instanceof PsiTypeVariable) {
for (int j = 0; j < extendsList.length; j++) {
final PsiType extendsType =
new Object() {
PsiType replaceWildCards(final PsiType type) {
if (type instanceof PsiWildcardType) {
final PsiWildcardType wildcard = ((PsiWildcardType)type);
final PsiType var = myTypeVariableFactory.create();
final PsiType bound = wildcard.getBound();
new Object() {
PsiType replaceWildCards(final PsiType type) {
if (type instanceof PsiWildcardType) {
final PsiWildcardType wildcard = ((PsiWildcardType)type);
final PsiType var = myTypeVariableFactory.create();
final PsiType bound = wildcard.getBound();
if (bound != null) {
if (wildcard.isExtends()) {
system.addSubtypeConstraint(Util.substituteType(replaceWildCards(bound), definedSubst), var);
}
else {
system.addSubtypeConstraint(var, Util.substituteType(replaceWildCards(bound), definedSubst));
}
if (bound != null) {
if (wildcard.isExtends()) {
system.addSubtypeConstraint(Util.banalize(Util.substituteType(replaceWildCards(bound), definedSubst)), var);
}
return var;
}
else if (type instanceof PsiClassType) {
final PsiClassType.ClassResolveResult result = Util.resolveType(type);
final PsiClass aClass = result.getElement();
final PsiSubstitutor aSubst = result.getSubstitutor();
if (aClass != null) {
PsiSubstitutor theSubst = PsiSubstitutor.EMPTY;
for (Iterator<PsiTypeParameter> i = aSubst.getSubstitutionMap().keySet().iterator(); i.hasNext();) {
final PsiTypeParameter p = i.next();
theSubst = theSubst.put(p, replaceWildCards(aSubst.substitute(p)));
}
return aClass.getManager().getElementFactory().createType(aClass, theSubst);
else {
system.addSubtypeConstraint(var, Util.banalize(Util.substituteType(replaceWildCards(bound), definedSubst)));
}
}
return type;
return var;
}
}.replaceWildCards(extendsList[j]);
else if (type instanceof PsiClassType) {
final PsiClassType.ClassResolveResult result = Util.resolveType(type);
final PsiClass aClass = result.getElement();
final PsiSubstitutor aSubst = result.getSubstitutor();
system.addSubtypeConstraint(Util.substituteType(extendsType, definedSubst), definedType);
if (aClass != null) {
PsiSubstitutor theSubst = PsiSubstitutor.EMPTY;
for (Iterator<PsiTypeParameter> i = aSubst.getSubstitutionMap().keySet().iterator(); i.hasNext();) {
final PsiTypeParameter p = i.next();
theSubst = theSubst.put(p, replaceWildCards(aSubst.substitute(p)));
}
return aClass.getManager().getElementFactory().createType(aClass, theSubst);
}
}
return type;
}
}.replaceWildCards(extendsList[j]);
system.addSubtypeConstraint(definedType, Util.banalize(Util.substituteType(extendsType, definedSubst)));
}
}
else {
@@ -731,21 +774,17 @@ public class SystemBuilder {
System system = new System(myProject, victims, myTypes, myTypeVariableFactory);
for (Iterator<PsiElement> i = victims.iterator(); i.hasNext();) {
PsiElement element = i.next();
final PsiElement element = i.next();
if (element instanceof PsiParameter) {
if (!verifyMethod(element, victims, helper)) {
continue;
continue;
}
element = myParameters.get(element);
}
else if (element instanceof PsiMethod) {
if (!verifyMethod(element, victims, helper)) {
continue;
continue;
}
element = mySuper.get(element);
}
}
@@ -761,17 +800,17 @@ public class SystemBuilder {
setType(element, definedType = defineType(p));
}
else {
definedType = defineType(element);
continue;
}
}
else if (element instanceof PsiMethod) {
final PsiMethod m = mySuper.get(element);
final PsiMethod m = myMethods.get(element);
if (m != null) {
system.addSubtypeConstraint(defineType(element), definedType = defineType(m));
}
else {
definedType = defineType(element);
continue;
}
}
else {
@@ -784,6 +823,21 @@ public class SystemBuilder {
for (Iterator<PsiElement> i = victims.iterator(); i.hasNext();) {
final PsiElement element = i.next();
if (element instanceof PsiParameter) {
final PsiParameter p = myParameters.get(element);
if (p == null) {
continue;
}
}
else if (element instanceof PsiMethod) {
final PsiMethod m = myMethods.get(element);
if (m == null) {
continue;
}
}
addUsage(system, element);
if (!(element instanceof PsiExpression)) {
@@ -6,6 +6,8 @@ import com.intellij.refactoring.typeCook.deductive.PsiExtendedTypeVisitor;
import com.intellij.refactoring.typeCook.Util;
import com.intellij.refactoring.typeCook.Bottom;
import com.intellij.psi.*;
import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.openapi.diagnostic.Logger;
@@ -13,10 +15,7 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.project.Project;
import com.intellij.util.IncorrectOperationException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.HashSet;
import java.util.Arrays;
import java.util.*;
/**
* Created by IntelliJ IDEA.
@@ -33,6 +32,35 @@ public class BindingFactory {
private HashSet<PsiTypeVariable> myBoundVariables;
private Project myProject;
private PsiClass[] getGreatestLowerClasses(final PsiClass aClass, final PsiClass bClass) {
if (InheritanceUtil.isInheritorOrSelf(aClass, bClass, true)) {
return new PsiClass[]{aClass};
}
if (InheritanceUtil.isInheritorOrSelf(bClass, aClass, true)) {
return new PsiClass[]{bClass};
}
final Set<PsiClass> descendants = new LinkedHashSet<PsiClass>();
new Object() {
public void getGreatestLowerClasses(final PsiClass aClass, final PsiClass bClass, final Set<PsiClass> descendants) {
if (aClass.isInheritor(bClass, true)) {
descendants.add(bClass);
}
else {
final PsiSearchHelper helper = aClass.getManager().getSearchHelper();
final PsiClass[] bSubs = helper.findInheritors(bClass, GlobalSearchScope.allScope(myProject), false);
for (int i = 0; i < bSubs.length; i++) {
getGreatestLowerClasses(bSubs[i], aClass, descendants);
}
}
}
}.getGreatestLowerClasses(aClass, bClass, descendants);
return descendants.toArray(new PsiClass[descendants.size()]);
}
private class BindingImpl extends Binding {
private PsiType[] myBindings;
private boolean myCyclic;
@@ -107,35 +135,35 @@ public class BindingFactory {
final int flag = (b1i == null ? 0 : 1) + (b2i == null ? 0 : 2);
switch (flag) {
case 0:
break;
case 0:
break;
case 1: /* b1(i)\b2(i) */
{
final PsiType type = b2.apply(b1i);
b3.myBindings[i] = type;
b3.myCyclic = type instanceof PsiTypeVariable;
}
break;
case 1: /* b1(i)\b2(i) */
{
final PsiType type = b2.apply(b1i);
b3.myBindings[i] = type;
b3.myCyclic = type instanceof PsiTypeVariable;
}
break;
case 2: /* b2(i)\b1(i) */
{
final PsiType type = b1.apply(b2i);
b3.myBindings[i] = type;
b3.myCyclic = type instanceof PsiTypeVariable;
}
break;
case 2: /* b2(i)\b1(i) */
{
final PsiType type = b1.apply(b2i);
b3.myBindings[i] = type;
b3.myCyclic = type instanceof PsiTypeVariable;
}
break;
case 3: /* b2(i) \cap b1(i) */
final Binding common = rise(b1i, b2i);
case 3: /* b2(i) \cap b1(i) */
final Binding common = rise(b1i, b2i);
if (common == null) {
return null;
}
if (common == null) {
return null;
}
final PsiType type = b2.apply(common.apply(b1i));
b3.myBindings[i] = type;
b3.myCyclic = type instanceof PsiTypeVariable;
final PsiType type = b2.apply(common.apply(b1i));
b3.myBindings[i] = type;
b3.myCyclic = type instanceof PsiTypeVariable;
}
}
@@ -157,7 +185,7 @@ public class BindingFactory {
}
private PsiType normalize(final PsiType t) {
if (t == null || t instanceof PsiTypeVariable){
if (t == null || t instanceof PsiTypeVariable) {
return Bottom.BOTTOM;
}
@@ -234,12 +262,40 @@ public class BindingFactory {
}
if (kindX != kindY) {
if (kindX == 4){
if (kindX == 4) {
return Binding.WORSE;
}
if (kindY == 4){
return Binding.BETTER;
if (kindY == 4) {
return Binding.BETTER;
}
if (kindX + kindY == 5) {
try {
final PsiElementFactory f = PsiManager.getInstance(myProject).getElementFactory();
final PsiType cloneable = f.createTypeFromText("java.lang.Cloneable", null);
final PsiType object = f.createTypeFromText("java.lang.Object", null);
final PsiType serializable = f.createTypeFromText("java.io.Serializable", null);
PsiType type = null;
int flag = 0;
if (kindX == 3) {
type = x;
flag = Binding.WORSE;
}
else {
type = y;
flag = Binding.BETTER;
}
if (type.equals(object) || type.equals(cloneable) || type.equals(serializable)) {
return flag;
}
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
return Binding.NONCOMPARABLE;
@@ -351,7 +407,7 @@ public class BindingFactory {
final PsiType type = binding.myBindings[i];
if (type == null) {
continue;
continue;
}
final int index = i;
@@ -393,78 +449,164 @@ public class BindingFactory {
Binding typeVar(PsiType x, PsiTypeVariable y);
}
interface Unifier {
Binding unify(PsiType x, PsiType y);
}
public Binding balance(final PsiType x, final PsiType y, final Balancer balancer) {
final int indicator = (x instanceof PsiTypeVariable ? 1 : 0) + (y instanceof PsiTypeVariable ? 2 : 0);
switch (indicator) {
case 0:
if (x instanceof PsiWildcardType || y instanceof PsiWildcardType) {
final PsiType xType = x instanceof PsiWildcardType ? ((PsiWildcardType)x).getBound() : x;
final PsiType yType = y instanceof PsiWildcardType ? ((PsiWildcardType)y).getBound() : y;
case 0:
if (x instanceof PsiWildcardType || y instanceof PsiWildcardType) {
final PsiType xType = x instanceof PsiWildcardType ? ((PsiWildcardType)x).getBound() : x;
final PsiType yType = y instanceof PsiWildcardType ? ((PsiWildcardType)y).getBound() : y;
return balance(xType, yType, balancer);
}
else if (x instanceof PsiArrayType || y instanceof PsiArrayType) {
final PsiType xType = x instanceof PsiArrayType ? ((PsiArrayType)x).getComponentType() : x;
final PsiType yType = y instanceof PsiArrayType ? ((PsiArrayType)y).getComponentType() : y;
return balance(xType, yType, balancer);
}
else if (x instanceof PsiArrayType || y instanceof PsiArrayType) {
final PsiType xType = x instanceof PsiArrayType ? ((PsiArrayType)x).getComponentType() : x;
final PsiType yType = y instanceof PsiArrayType ? ((PsiArrayType)y).getComponentType() : y;
return balance(xType, yType, balancer);
}
else if (x instanceof PsiClassType && y instanceof PsiClassType) {
final PsiClassType.ClassResolveResult resultX = Util.resolveType(x);
final PsiClassType.ClassResolveResult resultY = Util.resolveType(y);
return balance(xType, yType, balancer);
}
else if (x instanceof PsiClassType && y instanceof PsiClassType) {
final PsiClassType.ClassResolveResult resultX = Util.resolveType(x);
final PsiClassType.ClassResolveResult resultY = Util.resolveType(y);
final PsiClass xClass = resultX.getElement();
final PsiClass yClass = resultY.getElement();
final PsiClass xClass = resultX.getElement();
final PsiClass yClass = resultY.getElement();
if (xClass != null && yClass != null) {
final PsiSubstitutor ySubst = resultY.getSubstitutor();
if (xClass != null && yClass != null) {
final PsiSubstitutor ySubst = resultY.getSubstitutor();
PsiSubstitutor xSubst = resultX.getSubstitutor();
PsiSubstitutor xSubst = resultX.getSubstitutor();
if (!xClass.equals(yClass)) {
if (InheritanceUtil.isCorrectDescendant(xClass, yClass, true)) {
xSubst = TypeConversionUtil.getSuperClassSubstitutor(yClass, xClass, xSubst);
}
else {
return null;
}
}
if (!xClass.equals(yClass)) {
if (InheritanceUtil.isCorrectDescendant(xClass, yClass, true)) {
xSubst = TypeConversionUtil.getSuperClassSubstitutor(yClass, xClass, xSubst);
}
else {
return null;
}
}
Binding b = create();
Binding b = create();
for (Iterator<PsiTypeParameter> p = xSubst.getSubstitutionMap().keySet().iterator(); p.hasNext();) {
final PsiTypeParameter aParm = p.next();
final PsiType xType = xSubst.substitute(aParm);
final PsiType yType = ySubst.substitute(aParm);
for (Iterator<PsiTypeParameter> p = xSubst.getSubstitutionMap().keySet().iterator(); p.hasNext();) {
final PsiTypeParameter aParm = p.next();
final PsiType xType = xSubst.substitute(aParm);
final PsiType yType = ySubst.substitute(aParm);
final Binding b1 = balance(xType, yType, balancer);
final Binding b1 = unify(xType, yType, new Unifier() {
public Binding unify(final PsiType x, final PsiType y) {
return balance(x, y, balancer);
}
});
if (b1 == null) {
return null;
}
if (b1 == null) {
return null;
}
b = b.compose(b1);
}
b = b.compose(b1);
}
return b;
}
}
else if (x instanceof Bottom || y instanceof Bottom) {
return create();
}
else {
return null;
}
return b;
}
}
else if (y instanceof Bottom) {
return create();
}
else {
return null;
}
case 1:
return balancer.varType((PsiTypeVariable)x, y);
case 1:
return balancer.varType((PsiTypeVariable)x, y);
case 2:
return balancer.typeVar(x, (PsiTypeVariable)y);
case 2:
return balancer.typeVar(x, (PsiTypeVariable)y);
case 3:
return balancer.varVar((PsiTypeVariable)x, (PsiTypeVariable)y);
case 3:
return balancer.varVar((PsiTypeVariable)x, (PsiTypeVariable)y);
}
return null;
}
private Binding unify(final PsiType x, final PsiType y, final Unifier unifier) {
final int indicator = (x instanceof PsiTypeVariable ? 1 : 0) + (y instanceof PsiTypeVariable ? 2 : 0);
switch (indicator) {
case 0:
if (x instanceof PsiWildcardType || y instanceof PsiWildcardType) {
return unifier.unify(x, y);
}
else if (x instanceof PsiArrayType || y instanceof PsiArrayType) {
final PsiType xType = x instanceof PsiArrayType ? ((PsiArrayType)x).getComponentType() : x;
final PsiType yType = y instanceof PsiArrayType ? ((PsiArrayType)y).getComponentType() : y;
return unify(xType, yType, unifier);
}
else if (x instanceof PsiClassType && y instanceof PsiClassType) {
final PsiClassType.ClassResolveResult resultX = Util.resolveType(x);
final PsiClassType.ClassResolveResult resultY = Util.resolveType(y);
final PsiClass xClass = resultX.getElement();
final PsiClass yClass = resultY.getElement();
if (xClass != null && yClass != null) {
final PsiSubstitutor ySubst = resultY.getSubstitutor();
PsiSubstitutor xSubst = resultX.getSubstitutor();
if (!xClass.equals(yClass)) {
return null;
}
Binding b = create();
for (Iterator<PsiTypeParameter> p = xSubst.getSubstitutionMap().keySet().iterator(); p.hasNext();) {
final PsiTypeParameter aParm = p.next();
final PsiType xType = xSubst.substitute(aParm);
final PsiType yType = ySubst.substitute(aParm);
final Binding b1 = unify(xType, yType, unifier);
if (b1 == null) {
return null;
}
b = b.compose(b1);
}
return b;
}
}
else if (y instanceof Bottom) {
return create();
}
else {
return null;
}
case 1:
return create((PsiTypeVariable)x, y);
case 2:
return create((PsiTypeVariable)y, x);
case 3:
{
final PsiTypeVariable xVar = ((PsiTypeVariable)x);
final PsiTypeVariable yVar = ((PsiTypeVariable)y);
if (xVar.getIndex() == yVar.getIndex()) {
return create();
}
return xVar.getIndex() < yVar.getIndex() ? create(xVar, y) : create(yVar, x);
}
}
return null;
@@ -472,47 +614,45 @@ public class BindingFactory {
public Binding rise(final PsiType x, final PsiType y) {
return balance(x, y, new Balancer() {
public Binding varType(PsiTypeVariable x, PsiType y) {
return create(x, y);
}
public Binding varType(PsiTypeVariable x, PsiType y) {
return create(x, y);
}
public Binding varVar(PsiTypeVariable x, PsiTypeVariable y) {
final int xi = x.getIndex();
final int yi = y.getIndex();
public Binding varVar(PsiTypeVariable x, PsiTypeVariable y) {
final int xi = x.getIndex();
final int yi = y.getIndex();
if (xi < yi) {
return create(((PsiTypeVariable)x), y);
}
else if (yi < xi) {
return create(((PsiTypeVariable)y), x);
}
else {
return create();
}
}
if (xi < yi) {
return create(((PsiTypeVariable)x), y);
}
else if (yi < xi) {
return create(((PsiTypeVariable)y), x);
}
else {
return create();
}
}
public Binding typeVar(PsiType x, PsiTypeVariable y) {
return create(y, x);
}
});
public Binding typeVar(PsiType x, PsiTypeVariable y) {
return create(y, x);
}
});
}
public Binding sink(final PsiType x, final PsiType y) {
return balance(x, y, new Balancer() {
public Binding varType(PsiTypeVariable x, PsiType y) {
return create(x, Bottom.BOTTOM);
}
public Binding varType(PsiTypeVariable x, PsiType y) {
return create(x, Bottom.BOTTOM);
}
public Binding varVar(PsiTypeVariable x, PsiTypeVariable y) {
return create(x, Bottom.BOTTOM);
}
public Binding varVar(PsiTypeVariable x, PsiTypeVariable y) {
return create(x, Bottom.BOTTOM);
}
public Binding typeVar(PsiType x, PsiTypeVariable y) {
return create(y, x);
}
});
public Binding typeVar(PsiType x, PsiTypeVariable y) {
return create(y, x);
}
});
}
public LinkedList<Pair<PsiType, Binding>> union(final PsiType x, final PsiType y) {
@@ -547,7 +687,7 @@ public class BindingFactory {
list.addFirst(new Pair<PsiType, Binding>(risen.apply(x), risen));
}
else {
final PsiClass[] descendants = GenericsUtil.getGreatestLowerClasses(xClass, yClass);
final PsiClass[] descendants = getGreatestLowerClasses(xClass, yClass);
for (int i = 0; i < descendants.length; i++) {
final PsiClass descendant = descendants[i];
@@ -613,10 +753,14 @@ public class BindingFactory {
final Binding risen = rise(x, y);
if (risen == null) {
return;
}
final PsiElementFactory factory = xClass.getManager().getElementFactory();
list.addFirst(new Pair<PsiType, Binding>(risen.apply(x), risen));
list.addFirst(new Pair<PsiType, Binding>(Util.banalize(factory.createType(xClass, factory.createRawSubstitutor(xClass))),
create()));
}
else {
list.addFirst(new Pair<PsiType, Binding>(risen.apply(x), risen));
}
}
else {
final PsiClass[] ancestors = GenericsUtil.getLeastUpperClasses(xClass, yClass);
@@ -625,7 +769,7 @@ public class BindingFactory {
final PsiClass ancestor = ancestors[i];
if (ancestor.getQualifiedName().equals("java.lang.Object") && ancestors.length > 1) {
continue;
continue;
}
final PsiSubstitutor x2aSubst = TypeConversionUtil.getSuperClassSubstitutor(ancestor, xClass, xSubst);
@@ -0,0 +1,17 @@
class List<T> {
T t;
}
class Test{
class Super {
void f (List x){
x = new List<Integer>();
}
}
class Middle extends Super {
void f (List x){
x.t = "";
}
}
}
@@ -0,0 +1,17 @@
class List<T> {
T t;
}
class Test{
class Super {
void f (List x){
x = new List<Integer>();
}
}
class Middle extends Super {
void f (List x){
x.t = "";
}
}
}
@@ -10,6 +10,7 @@ class Test{
class Middle extends Super {
void f (List x){
g(x);
x.t = "";
}
@@ -10,6 +10,7 @@ class Test{
class Middle extends Super {
void f (List x){
g(x);
x.t = "";
}
@@ -3,17 +3,7 @@ class List<T> {
}
class Test{
class Super {
void f (List x){
x = new List<Integer>();
}
}
class Middle extends Super {
void f (List x){
x.t = "";
}
List g (){
return new List<Integer>();
}
@@ -21,7 +11,6 @@ class Test{
class Sub extends Middle{
List g (){
}
}
}
@@ -3,17 +3,7 @@ class List<T> {
}
class Test{
class Super {
void f (List x){
x = new List<Integer>();
}
}
class Middle extends Super {
void f (List x){
x.t = "";
}
List g (){
return new List<Integer>();
}
@@ -21,7 +11,6 @@ class Test{
class Sub extends Middle{
List g (){
}
}
}