Search in sources :

Example 1 with Subtype

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;
}
Also used : Constraint(com.intellij.refactoring.typeCook.deductive.builder.Constraint) Subtype(com.intellij.refactoring.typeCook.deductive.builder.Subtype)

Aggregations

Constraint (com.intellij.refactoring.typeCook.deductive.builder.Constraint)1 Subtype (com.intellij.refactoring.typeCook.deductive.builder.Subtype)1