Search in sources :

Example 1 with TypeMigrationUsageInfo

use of com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo in project intellij-community by JetBrains.

the class TypeEvaluator method getReport.

public String getReport() {
    final StringBuilder buffer = new StringBuilder();
    final String[] t = new String[myTypeMap.size()];
    int k = 0;
    for (final TypeMigrationUsageInfo info : myTypeMap.keySet()) {
        final LinkedList<PsiType> types = myTypeMap.get(info);
        final StringBuilder b = new StringBuilder();
        if (types != null) {
            b.append(info.getElement()).append(" : ");
            b.append(StringUtil.join(types, psiType -> psiType.getCanonicalText(), " "));
            b.append("\n");
        }
        t[k++] = b.toString();
    }
    Arrays.sort(t);
    for (String aT : t) {
        buffer.append(aT);
    }
    return buffer.toString();
}
Also used : TypeConversionUtil(com.intellij.psi.util.TypeConversionUtil) Arrays(java.util.Arrays) IElementType(com.intellij.psi.tree.IElementType) StringUtil(com.intellij.openapi.util.text.StringUtil) HashMap(com.intellij.util.containers.HashMap) TypeMigrationUsageInfo(com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo) Nullable(org.jetbrains.annotations.Nullable) PsiTreeUtil(com.intellij.psi.util.PsiTreeUtil) Comparing(com.intellij.openapi.util.Comparing) Function(com.intellij.util.Function) Map(java.util.Map) Pair(com.intellij.openapi.util.Pair) PsiImplUtil(com.intellij.psi.impl.PsiImplUtil) InheritanceUtil(com.intellij.psi.util.InheritanceUtil) PsiUtil(com.intellij.psi.util.PsiUtil) com.intellij.psi(com.intellij.psi) Logger(com.intellij.openapi.diagnostic.Logger) NotNull(org.jetbrains.annotations.NotNull) LinkedList(java.util.LinkedList) TypeMigrationUsageInfo(com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo)

Example 2 with TypeMigrationUsageInfo

use of com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo in project intellij-community by JetBrains.

the class TypeEvaluator method evaluateType.

@Nullable
public PsiType evaluateType(final PsiExpression expr) {
    if (expr == null)
        return null;
    final LinkedList<PsiType> e = myTypeMap.get(new TypeMigrationUsageInfo(expr));
    if (e != null) {
        return e.getFirst();
    }
    if (expr instanceof PsiArrayAccessExpression) {
        final PsiType at = evaluateType(((PsiArrayAccessExpression) expr).getArrayExpression());
        if (at instanceof PsiArrayType) {
            return ((PsiArrayType) at).getComponentType();
        }
    } else if (expr instanceof PsiAssignmentExpression) {
        return evaluateType(((PsiAssignmentExpression) expr).getLExpression());
    } else if (expr instanceof PsiMethodCallExpression) {
        final PsiMethodCallExpression call = (PsiMethodCallExpression) expr;
        final JavaResolveResult resolveResult = call.resolveMethodGenerics();
        final PsiMethod method = (PsiMethod) resolveResult.getElement();
        if (method != null) {
            final PsiParameter[] parameters = method.getParameterList().getParameters();
            final PsiExpression[] actualParms = call.getArgumentList().getExpressions();
            return PsiUtil.captureToplevelWildcards(createMethodSubstitution(parameters, actualParms, method, call, resolveResult.getSubstitutor(), false).substitute(evaluateType(call.getMethodExpression())), expr);
        }
    } else if (expr instanceof PsiPolyadicExpression) {
        final PsiExpression[] operands = ((PsiPolyadicExpression) expr).getOperands();
        final IElementType sign = ((PsiPolyadicExpression) expr).getOperationTokenType();
        PsiType lType = operands.length > 0 ? evaluateType(operands[0]) : null;
        for (int i = 1; i < operands.length; i++) {
            lType = TypeConversionUtil.calcTypeForBinaryExpression(lType, evaluateType(operands[i]), sign, true);
        }
        return lType;
    } else if (expr instanceof PsiPostfixExpression) {
        return evaluateType(((PsiPostfixExpression) expr).getOperand());
    } else if (expr instanceof PsiPrefixExpression) {
        return evaluateType(((PsiPrefixExpression) expr).getOperand());
    } else if (expr instanceof PsiParenthesizedExpression) {
        return evaluateType(((PsiParenthesizedExpression) expr).getExpression());
    } else if (expr instanceof PsiConditionalExpression) {
        final PsiExpression thenExpression = ((PsiConditionalExpression) expr).getThenExpression();
        final PsiExpression elseExpression = ((PsiConditionalExpression) expr).getElseExpression();
        final PsiType thenType = evaluateType(thenExpression);
        final PsiType elseType = evaluateType(elseExpression);
        switch((thenType == null ? 0 : 1) + (elseType == null ? 0 : 2)) {
            case 0:
                return expr.getType();
            case 1:
                return thenType;
            case 2:
                return elseType;
            case 3:
                if (TypeConversionUtil.areTypesConvertible(thenType, elseType)) {
                    return thenType;
                } else if (TypeConversionUtil.areTypesConvertible(elseType, thenType)) {
                    return elseType;
                } else {
                    switch((thenType.equals(thenExpression.getType()) ? 0 : 1) + (elseType.equals(elseExpression.getType()) ? 0 : 2)) {
                        case 0:
                            return expr.getType();
                        case 1:
                            return thenType;
                        case 2:
                            return elseType;
                        case 3:
                            return expr.getType();
                        default:
                            LOG.error("Must not happen.");
                            return null;
                    }
                }
            default:
                LOG.error("Must not happen.");
        }
    } else if (expr instanceof PsiNewExpression) {
        final PsiExpression qualifier = ((PsiNewExpression) expr).getQualifier();
        if (qualifier != null) {
            final PsiClassType.ClassResolveResult qualifierResult = resolveType(evaluateType(qualifier));
            if (qualifierResult.getElement() != null) {
                final PsiSubstitutor qualifierSubs = qualifierResult.getSubstitutor();
                final PsiClassType.ClassResolveResult result = resolveType(expr.getType());
                if (result.getElement() != null) {
                    final PsiClass aClass = result.getElement();
                    return JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory().createType(aClass, result.getSubstitutor().putAll(qualifierSubs));
                }
            }
        }
    } else if (expr instanceof PsiFunctionalExpression) {
        final PsiType functionalInterfaceType = ((PsiFunctionalExpression) expr).getFunctionalInterfaceType();
        if (functionalInterfaceType != null) {
            return functionalInterfaceType;
        }
    } else if (expr instanceof PsiReferenceExpression) {
        final PsiType type = evaluateReferenceExpressionType(expr);
        if (type != null) {
            return PsiImplUtil.normalizeWildcardTypeByPosition(type, expr);
        }
    } else if (expr instanceof PsiSuperExpression) {
        final PsiClass psiClass = PsiTreeUtil.getParentOfType(expr, PsiClass.class);
        if (psiClass != null) {
            final PsiClass superClass = psiClass.getSuperClass();
            if (superClass != null) {
                return getType(new TypeMigrationUsageInfo(superClass));
            }
        }
    }
    return getType(expr);
}
Also used : TypeMigrationUsageInfo(com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo) IElementType(com.intellij.psi.tree.IElementType) Nullable(org.jetbrains.annotations.Nullable)

Example 3 with TypeMigrationUsageInfo

use of com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo in project intellij-community by JetBrains.

the class TypeMigrationLabeler method addMigrationRoot.

boolean addMigrationRoot(PsiElement element, PsiType type, final PsiElement place, boolean alreadyProcessed, final boolean isContraVariantPosition, final boolean userDefinedType) {
    if (type.equals(PsiType.NULL)) {
        return false;
    }
    final PsiElement resolved = Util.normalizeElement(element);
    if (!canBeRoot(resolved, myRules.getSearchScope())) {
        return false;
    }
    final PsiType originalType = getElementType(resolved);
    LOG.assertTrue(originalType != null);
    type = userDefinedType ? type : TypeEvaluator.substituteType(type, originalType, isContraVariantPosition);
    if (!userDefinedType) {
        final Set<PsiTypeParameter> collector;
        if (type instanceof PsiClassType) {
            collector = type.accept(new PsiExtendedTypeVisitor<Set<PsiTypeParameter>>() {

                private final Set<PsiTypeParameter> myResult = new HashSet<>();

                @Override
                public Set<PsiTypeParameter> visitClassType(PsiClassType classType) {
                    super.visitClassType(classType);
                    final PsiClass resolved = classType.resolve();
                    if (resolved instanceof PsiTypeParameter) {
                        myResult.add((PsiTypeParameter) resolved);
                    }
                    return myResult;
                }
            });
        } else {
            collector = Collections.emptySet();
        }
        if (typeContainsTypeParameters(originalType, collector))
            return false;
    }
    if (type instanceof PsiCapturedWildcardType) {
        return false;
    }
    if (resolved instanceof PsiMethod) {
        final PsiMethod method = ((PsiMethod) resolved);
        final PsiClass containingClass = method.getContainingClass();
        if (containingClass instanceof PsiAnonymousClass) {
            final HierarchicalMethodSignature signature = method.getHierarchicalMethodSignature();
            final List<HierarchicalMethodSignature> superSignatures = signature.getSuperSignatures();
            if (!superSignatures.isEmpty()) {
                final HierarchicalMethodSignature superSignature = superSignatures.get(0);
                final PsiSubstitutor substitutor = superSignature.getSubstitutor();
                if (!substitutor.getSubstitutionMap().isEmpty()) {
                    final PsiMethod superMethod = superSignature.getMethod();
                    final PsiType superReturnType = superMethod.getReturnType();
                    if (superReturnType instanceof PsiClassType) {
                        final PsiClass resolvedClass = ((PsiClassType) superReturnType).resolve();
                        if (resolvedClass instanceof PsiTypeParameter) {
                            final PsiType expectedReturnType = substitutor.substitute((PsiTypeParameter) resolvedClass);
                            if (Comparing.equal(expectedReturnType, method.getReturnType())) {
                                final PsiClassType baseClassType = ((PsiAnonymousClass) containingClass).getBaseClassType();
                                final PsiClassType.ClassResolveResult result = baseClassType.resolveGenerics();
                                final PsiClass anonymousBaseClass = result.getElement();
                                final PsiSubstitutor superHierarchySubstitutor = TypeConversionUtil.getClassSubstitutor(superMethod.getContainingClass(), anonymousBaseClass, PsiSubstitutor.EMPTY);
                                final PsiType maybeTypeParameter = superHierarchySubstitutor.substitute((PsiTypeParameter) resolvedClass);
                                if (maybeTypeParameter instanceof PsiClassType && ((PsiClassType) maybeTypeParameter).resolve() instanceof PsiTypeParameter) {
                                    final PsiSubstitutor newSubstitutor = result.getSubstitutor().put((PsiTypeParameter) ((PsiClassType) maybeTypeParameter).resolve(), type);
                                    addRoot(new TypeMigrationUsageInfo(((PsiAnonymousClass) containingClass).getBaseClassReference().getParameterList()), new PsiImmediateClassType(anonymousBaseClass, newSubstitutor), place, alreadyProcessed);
                                }
                            }
                        }
                    }
                }
            }
        }
        final PsiMethod[] methods = OverridingMethodsSearch.search(method).toArray(PsiMethod.EMPTY_ARRAY);
        final OverriderUsageInfo[] overriders = new OverriderUsageInfo[methods.length];
        for (int i = -1; i < methods.length; i++) {
            final TypeMigrationUsageInfo m;
            if (i < 0) {
                final OverriddenUsageInfo overriddenUsageInfo = new OverriddenUsageInfo(method);
                m = overriddenUsageInfo;
                final String newMethodName = isMethodNameCanBeChanged(method);
                if (newMethodName != null) {
                    final MigrateGetterNameSetting migrateGetterNameSetting = myRules.getConversionSettings(MigrateGetterNameSetting.class);
                    migrateGetterNameSetting.askUserIfNeed(overriddenUsageInfo, newMethodName, myTypeEvaluator.getType(myCurrentRoot));
                }
            } else {
                overriders[i] = new OverriderUsageInfo(methods[i], method);
                m = overriders[i];
            }
            alreadyProcessed = addRoot(m, type, place, alreadyProcessed);
        }
        return !alreadyProcessed;
    } else if (resolved instanceof PsiParameter && ((PsiParameter) resolved).getDeclarationScope() instanceof PsiMethod) {
        final PsiMethod method = (PsiMethod) ((PsiParameter) resolved).getDeclarationScope();
        final int index = method.getParameterList().getParameterIndex(((PsiParameter) resolved));
        final PsiMethod[] methods = OverridingMethodsSearch.search(method).toArray(PsiMethod.EMPTY_ARRAY);
        final OverriderUsageInfo[] overriders = new OverriderUsageInfo[methods.length];
        final OverriddenUsageInfo overriddenUsageInfo = new OverriddenUsageInfo(method.getParameterList().getParameters()[index]);
        for (int i = -1; i < methods.length; i++) {
            final PsiMethod m = i < 0 ? method : methods[i];
            final PsiParameter p = m.getParameterList().getParameters()[index];
            final TypeMigrationUsageInfo paramUsageInfo;
            if (i < 0) {
                paramUsageInfo = overriddenUsageInfo;
            } else {
                overriders[i] = new OverriderUsageInfo(p, method);
                paramUsageInfo = overriders[i];
            }
            alreadyProcessed = addRoot(paramUsageInfo, type, place, alreadyProcessed);
        }
        return !alreadyProcessed;
    } else {
        return !addRoot(new TypeMigrationUsageInfo(resolved), type, place, alreadyProcessed);
    }
}
Also used : PsiImmediateClassType(com.intellij.psi.impl.source.PsiImmediateClassType) TypeMigrationUsageInfo(com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo) PsiExtendedTypeVisitor(com.intellij.refactoring.typeCook.deductive.PsiExtendedTypeVisitor) OverriddenUsageInfo(com.intellij.refactoring.typeMigration.usageInfo.OverriddenUsageInfo) OverriderUsageInfo(com.intellij.refactoring.typeMigration.usageInfo.OverriderUsageInfo)

Example 4 with TypeMigrationUsageInfo

use of com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo in project intellij-community by JetBrains.

the class TypeMigrationLabeler method sortMigratedUsages.

private TypeMigrationUsageInfo[] sortMigratedUsages(TypeMigrationUsageInfo[] infos) {
    final DFSTBuilder<TypeMigrationUsageInfo> builder = new DFSTBuilder<>(GraphGenerator.generate(new InboundSemiGraph<TypeMigrationUsageInfo>() {

        @Override
        public Collection<TypeMigrationUsageInfo> getNodes() {
            final Set<TypeMigrationUsageInfo> infos = new HashSet<>();
            for (Map.Entry<TypeMigrationUsageInfo, HashSet<Pair<TypeMigrationUsageInfo, PsiType>>> entry : myRootsTree.entrySet()) {
                infos.add(entry.getKey());
                infos.addAll(ContainerUtil.map(entry.getValue(), pair -> pair.getFirst()));
            }
            return infos;
        }

        @Override
        public Iterator<TypeMigrationUsageInfo> getIn(TypeMigrationUsageInfo n) {
            final HashSet<Pair<TypeMigrationUsageInfo, PsiType>> rawNodes = myRootsTree.get(n);
            if (rawNodes == null) {
                return Collections.<TypeMigrationUsageInfo>emptyList().iterator();
            }
            final List<TypeMigrationUsageInfo> in = ContainerUtil.map(rawNodes, pair -> pair.getFirst());
            return in.iterator();
        }
    }));
    final Comparator<TypeMigrationUsageInfo> cmp = builder.comparator();
    Arrays.sort(infos, (info1, info2) -> {
        final TypeMigrationUsageInfo i1 = info1.getOwnerRoot();
        final TypeMigrationUsageInfo i2 = info2.getOwnerRoot();
        if (i1 == null && i2 == null) {
            return 0;
        }
        if (i1 == null) {
            return 1;
        }
        if (i2 == null) {
            return -1;
        }
        final PsiElement element1 = info1.getElement();
        final PsiElement element2 = info2.getElement();
        LOG.assertTrue(element1 != null && element2 != null);
        if (element1.equals(element2)) {
            return 0;
        }
        final TextRange range1 = element1.getTextRange();
        final TextRange range2 = element2.getTextRange();
        if (range1.contains(range2)) {
            return 1;
        }
        if (range2.contains(range1)) {
            return -1;
        }
        final int res = cmp.compare(i1, i2);
        if (res != 0) {
            return res;
        }
        return range2.getStartOffset() - range1.getStartOffset();
    });
    return infos;
}
Also used : PsiImmediateClassType(com.intellij.psi.impl.source.PsiImmediateClassType) TypeConversionUtil(com.intellij.psi.util.TypeConversionUtil) java.util(java.util) PsiDocTagValue(com.intellij.psi.javadoc.PsiDocTagValue) OverriddenUsageInfo(com.intellij.refactoring.typeMigration.usageInfo.OverriddenUsageInfo) DFSTBuilder(com.intellij.util.graph.DFSTBuilder) UsageInfo(com.intellij.usageView.UsageInfo) SearchScope(com.intellij.psi.search.SearchScope) PsiExtendedTypeVisitor(com.intellij.refactoring.typeCook.deductive.PsiExtendedTypeVisitor) ContainerUtil(com.intellij.util.containers.ContainerUtil) THashMap(gnu.trove.THashMap) TypeMigrationUsageInfo(com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo) PsiTreeUtil(com.intellij.psi.util.PsiTreeUtil) Comparing(com.intellij.openapi.util.Comparing) RenameProcessor(com.intellij.refactoring.rename.RenameProcessor) Semaphore(com.intellij.util.concurrency.Semaphore) Project(com.intellij.openapi.project.Project) PsiUtil(com.intellij.psi.util.PsiUtil) Messages(com.intellij.openapi.ui.Messages) Logger(com.intellij.openapi.diagnostic.Logger) ProjectRootManager(com.intellij.openapi.roots.ProjectRootManager) JavaLanguage(com.intellij.lang.java.JavaLanguage) MultiMap(com.intellij.util.containers.MultiMap) OverriderUsageInfo(com.intellij.refactoring.typeMigration.usageInfo.OverriderUsageInfo) ReferencesSearch(com.intellij.psi.search.searches.ReferencesSearch) StringUtil(com.intellij.openapi.util.text.StringUtil) OverridingMethodsSearch(com.intellij.psi.search.searches.OverridingMethodsSearch) GenerateMembersUtil(com.intellij.codeInsight.generation.GenerateMembersUtil) TextRange(com.intellij.openapi.util.TextRange) TestOnly(org.jetbrains.annotations.TestOnly) Nullable(org.jetbrains.annotations.Nullable) InboundSemiGraph(com.intellij.util.graph.InboundSemiGraph) PsiSearchScopeUtil(com.intellij.psi.search.PsiSearchScopeUtil) GraphGenerator(com.intellij.util.graph.GraphGenerator) Pair(com.intellij.openapi.util.Pair) ApplicationManager(com.intellij.openapi.application.ApplicationManager) GetterSetterPrototypeProvider(com.intellij.codeInsight.generation.GetterSetterPrototypeProvider) com.intellij.psi(com.intellij.psi) com.intellij.util(com.intellij.util) NotNull(org.jetbrains.annotations.NotNull) javax.swing(javax.swing) TextRange(com.intellij.openapi.util.TextRange) TypeMigrationUsageInfo(com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo) InboundSemiGraph(com.intellij.util.graph.InboundSemiGraph) DFSTBuilder(com.intellij.util.graph.DFSTBuilder) THashMap(gnu.trove.THashMap) MultiMap(com.intellij.util.containers.MultiMap) Pair(com.intellij.openapi.util.Pair)

Example 5 with TypeMigrationUsageInfo

use of com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo in project intellij-community by JetBrains.

the class MigrationUsagesPanel method showRootUsages.

public void showRootUsages(UsageInfo root, UsageInfo migration, final TypeMigrationLabeler labeler) {
    final PsiElement rootElement = root.getElement();
    if (rootElement == null)
        return;
    final Set<PsiElement> usages = labeler.getTypeUsages((TypeMigrationUsageInfo) migration, ((TypeMigrationUsageInfo) root));
    if (usages != null) {
        final List<UsageInfo> infos = new ArrayList<>(usages.size());
        for (PsiElement usage : usages) {
            if (usage != null && usage.isValid()) {
                infos.add(new UsageInfo(usage));
            }
        }
        showUsages(new PsiElement[] { rootElement }, infos.toArray(new UsageInfo[infos.size()]));
    } else {
        showUsages(new PsiElement[] { rootElement }, new UsageInfo[] { migration });
    }
}
Also used : ArrayList(java.util.ArrayList) PsiElement(com.intellij.psi.PsiElement) TypeMigrationUsageInfo(com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo) TypeMigrationUsageInfo(com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo) UsageInfo(com.intellij.usageView.UsageInfo)

Aggregations

TypeMigrationUsageInfo (com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo)17 Pair (com.intellij.openapi.util.Pair)7 NotNull (org.jetbrains.annotations.NotNull)5 UsageInfo (com.intellij.usageView.UsageInfo)4 Logger (com.intellij.openapi.diagnostic.Logger)3 Comparing (com.intellij.openapi.util.Comparing)3 StringUtil (com.intellij.openapi.util.text.StringUtil)3 com.intellij.psi (com.intellij.psi)3 PsiImmediateClassType (com.intellij.psi.impl.source.PsiImmediateClassType)3 PsiTreeUtil (com.intellij.psi.util.PsiTreeUtil)3 PsiUtil (com.intellij.psi.util.PsiUtil)3 TypeConversionUtil (com.intellij.psi.util.TypeConversionUtil)3 PsiExtendedTypeVisitor (com.intellij.refactoring.typeCook.deductive.PsiExtendedTypeVisitor)3 OverriddenUsageInfo (com.intellij.refactoring.typeMigration.usageInfo.OverriddenUsageInfo)3 OverriderUsageInfo (com.intellij.refactoring.typeMigration.usageInfo.OverriderUsageInfo)3 Nullable (org.jetbrains.annotations.Nullable)3 GenerateMembersUtil (com.intellij.codeInsight.generation.GenerateMembersUtil)2 GetterSetterPrototypeProvider (com.intellij.codeInsight.generation.GetterSetterPrototypeProvider)2 JavaLanguage (com.intellij.lang.java.JavaLanguage)2 ApplicationManager (com.intellij.openapi.application.ApplicationManager)2