use of com.intellij.refactoring.typeCook.deductive.builder.Subtype in project intellij-community by JetBrains.
the class BindingFactory method balance.
public Binding balance(final PsiType x, final PsiType y, final Balancer balancer, final Set<Constraint> constraints) {
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;
switch((x instanceof PsiWildcardType ? 1 : 0) + (y instanceof PsiWildcardType ? 2 : 0)) {
case 1:
if (((PsiWildcardType) x).isExtends()) {
/* ? extends T1, T2 */
return null;
} else {
/* ? super T1, T2 */
if (xType != null && !CommonClassNames.JAVA_LANG_OBJECT.equals(xType.getCanonicalText())) {
return null;
}
return create();
}
case 2:
if (((PsiWildcardType) y).isExtends()) {
/* T1, ? extends T2 */
if (yType instanceof PsiTypeVariable) {
final PsiTypeVariable beta = myFactory.create();
if (constraints != null) {
constraints.add(new Subtype(beta, yType));
if (x != null) {
constraints.add(new Subtype(x, yType));
}
}
return create();
} else {
if (constraints != null && xType != null && yType != null) {
constraints.add(new Subtype(xType, yType));
}
return balance(xType, yType, balancer, constraints);
}
} else {
/* T1, ? super T2 */
if (yType instanceof PsiTypeVariable) {
final PsiTypeVariable beta = myFactory.create();
if (constraints != null) {
if (x != null)
constraints.add(new Subtype(x, beta));
constraints.add(new Subtype(yType, beta));
}
return create();
} else {
if (constraints != null && yType != null && xType != null) {
constraints.add(new Subtype(yType, xType));
}
return balance(xType, yType, balancer, constraints);
}
}
case 3:
switch((((PsiWildcardType) x).isExtends() ? 0 : 1) + (((PsiWildcardType) y).isExtends() ? 0 : 2)) {
case 0:
/* ? super T1, ? super T2 */
if (constraints != null && xType != null && yType != null) {
constraints.add(new Subtype(yType, xType));
}
return balance(xType, yType, balancer, constraints);
case 1:
/* ? extends T1, ? super T2 */
if (constraints != null && xType != null && yType != null) {
constraints.add(new Subtype(xType, yType));
}
return balance(xType, yType, balancer, constraints);
case 2:
/* ? super T1, ? extends T2*/
return null;
case 3:
/* ? extends T1, ? extends T2*/
if (constraints != null && xType != null && yType != null) {
constraints.add(new Subtype(xType, yType));
}
return balance(xType, yType, balancer, constraints);
}
}
return create();
} 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, constraints);
} 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 = TypeConversionUtil.getClassSubstitutor(yClass, xClass, resultX.getSubstitutor());
if (xSubst == null)
return null;
Binding b = create();
for (final PsiTypeParameter aParm : xSubst.getSubstitutionMap().keySet()) {
final PsiType xType = xSubst.substitute(aParm);
final PsiType yType = ySubst.substitute(aParm);
final Binding b1 = unify(xType, yType, new Unifier() {
public Binding unify(final PsiType x, final PsiType y) {
return balance(x, y, balancer, constraints);
}
});
if (b1 == null) {
return null;
}
b = b.compose(b1);
}
return b;
}
} else if (y instanceof Bottom) {
return create();
} else {
return null;
}
break;
case 1:
return balancer.varType((PsiTypeVariable) x, y);
case 2:
return balancer.typeVar(x, (PsiTypeVariable) y);
case 3:
return balancer.varVar((PsiTypeVariable) x, (PsiTypeVariable) y);
}
return null;
}
Aggregations