Search in sources :

Example 11 with MethodCandidateInfo

use of com.intellij.psi.infos.MethodCandidateInfo in project intellij-community by JetBrains.

the class JavaMethodsConflictResolver method checkSameSignatures.

protected void checkSameSignatures(@NotNull List<CandidateInfo> conflicts, FactoryMap<MethodCandidateInfo, PsiSubstitutor> map) {
    // candidates should go in order of class hierarchy traversal
    // in order for this to work
    Map<MethodSignature, CandidateInfo> signatures = new THashMap<>(conflicts.size());
    Set<PsiMethod> superMethods = new HashSet<>();
    for (CandidateInfo conflict : conflicts) {
        final PsiMethod method = ((MethodCandidateInfo) conflict).getElement();
        final PsiClass containingClass = method.getContainingClass();
        final boolean isInterface = containingClass != null && containingClass.isInterface();
        for (HierarchicalMethodSignature methodSignature : method.getHierarchicalMethodSignature().getSuperSignatures()) {
            final PsiMethod superMethod = methodSignature.getMethod();
            if (!isInterface) {
                superMethods.add(superMethod);
            } else {
                final PsiClass aClass = superMethod.getContainingClass();
                if (aClass != null && !CommonClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) {
                    superMethods.add(superMethod);
                }
            }
        }
    }
    nextConflict: for (int i = 0; i < conflicts.size(); i++) {
        ProgressManager.checkCanceled();
        CandidateInfo info = conflicts.get(i);
        PsiMethod method = (PsiMethod) info.getElement();
        if (!method.hasModifierProperty(PsiModifier.STATIC) && superMethods.contains(method)) {
            conflicts.remove(i);
            i--;
            continue;
        }
        PsiClass class1 = method.getContainingClass();
        PsiSubstitutor infoSubstitutor = getSubstitutor((MethodCandidateInfo) info, map);
        MethodSignature signature = method.getSignature(infoSubstitutor);
        CandidateInfo existing = signatures.get(signature);
        if (existing == null) {
            signatures.put(signature, info);
            continue;
        }
        PsiMethod existingMethod = (PsiMethod) existing.getElement();
        PsiClass existingClass = existingMethod.getContainingClass();
        if (class1 != null && existingClass != null) {
            //prefer interface methods to methods from Object
            if (class1.isInterface() && CommonClassNames.JAVA_LANG_OBJECT.equals(existingClass.getQualifiedName())) {
                signatures.put(signature, info);
                continue;
            } else if (existingClass.isInterface() && CommonClassNames.JAVA_LANG_OBJECT.equals(class1.getQualifiedName())) {
                conflicts.remove(info);
                i--;
                continue;
            }
        }
        if (method == existingMethod) {
            PsiElement scope1 = info.getCurrentFileResolveScope();
            PsiElement scope2 = existing.getCurrentFileResolveScope();
            if (scope1 instanceof PsiClass && scope2 instanceof PsiClass && PsiTreeUtil.isAncestor(scope1, scope2, true) && !existing.isAccessible()) {
                //prefer methods from outer class to inaccessible base class methods
                signatures.put(signature, info);
                continue;
            }
        }
        // filter out methods with incorrect inferred bounds (for unrelated methods only)
        boolean existingTypeParamAgree = areTypeParametersAgree(existing);
        boolean infoTypeParamAgree = areTypeParametersAgree(info);
        if (existingTypeParamAgree && !infoTypeParamAgree && !PsiSuperMethodImplUtil.isSuperMethodSmart(method, existingMethod)) {
            conflicts.remove(i);
            i--;
            continue;
        }
        if (!existingTypeParamAgree && infoTypeParamAgree && !PsiSuperMethodImplUtil.isSuperMethodSmart(existingMethod, method)) {
            signatures.put(signature, info);
            int index = conflicts.indexOf(existing);
            conflicts.remove(index);
            i--;
            continue;
        }
        if (InheritanceUtil.isInheritorOrSelf(class1, existingClass, true) || InheritanceUtil.isInheritorOrSelf(existingClass, class1, true)) {
            PsiParameter[] parameters = method.getParameterList().getParameters();
            final PsiParameter[] existingParameters = existingMethod.getParameterList().getParameters();
            for (int i1 = 0, parametersLength = parameters.length; i1 < parametersLength; i1++) {
                if (parameters[i1].getType() instanceof PsiArrayType && !(existingParameters[i1].getType() instanceof PsiArrayType)) {
                    //prefer more specific type
                    signatures.put(signature, info);
                    continue nextConflict;
                }
            }
            PsiType returnType1 = method.getReturnType();
            PsiType returnType2 = existingMethod.getReturnType();
            if (returnType1 != null && returnType2 != null) {
                returnType1 = infoSubstitutor.substitute(returnType1);
                returnType2 = getSubstitutor((MethodCandidateInfo) existing, map).substitute(returnType2);
                if (!returnType1.equals(returnType2) && returnType1.isAssignableFrom(returnType2)) {
                    conflicts.remove(i);
                    i--;
                    continue;
                }
            }
            // prefer derived class
            signatures.put(signature, info);
        } else {
            final PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(myArgumentsList, PsiMethodCallExpression.class);
            if (methodCallExpression != null) {
                final PsiReferenceExpression expression = methodCallExpression.getMethodExpression();
                final PsiExpression qualifierExpression = expression.getQualifierExpression();
                PsiClass currentClass;
                if (qualifierExpression != null) {
                    currentClass = PsiUtil.resolveClassInClassTypeOnly(qualifierExpression.getType());
                } else {
                    currentClass = PsiTreeUtil.getParentOfType(expression, PsiClass.class);
                }
                if (currentClass != null && existingClass != null && class1 != null) {
                    final PsiSubstitutor eSubstitutor = TypeConversionUtil.getMaybeSuperClassSubstitutor(existingClass, currentClass, PsiSubstitutor.EMPTY, null);
                    final PsiSubstitutor cSubstitutor = TypeConversionUtil.getMaybeSuperClassSubstitutor(class1, currentClass, PsiSubstitutor.EMPTY, null);
                    if (eSubstitutor != null && cSubstitutor != null && MethodSignatureUtil.areSignaturesEqual(existingMethod.getSignature(eSubstitutor), method.getSignature(cSubstitutor))) {
                        final PsiType returnType = eSubstitutor.substitute(existingMethod.getReturnType());
                        final PsiType returnType1 = cSubstitutor.substitute(method.getReturnType());
                        if (returnType != null && returnType1 != null && !returnType1.equals(returnType)) {
                            if (TypeConversionUtil.isAssignable(returnType, returnType1, false)) {
                                if (class1.isInterface() && !existingClass.isInterface())
                                    continue;
                                conflicts.remove(existing);
                            } else {
                                if (!TypeConversionUtil.isAssignable(returnType1, returnType, false))
                                    continue;
                                conflicts.remove(i);
                            }
                            i--;
                            break;
                        }
                    }
                }
            }
        }
    }
}
Also used : CandidateInfo(com.intellij.psi.infos.CandidateInfo) MethodCandidateInfo(com.intellij.psi.infos.MethodCandidateInfo) THashMap(gnu.trove.THashMap) MethodCandidateInfo(com.intellij.psi.infos.MethodCandidateInfo) HashSet(com.intellij.util.containers.HashSet) THashSet(gnu.trove.THashSet)

Example 12 with MethodCandidateInfo

use of com.intellij.psi.infos.MethodCandidateInfo in project intellij-community by JetBrains.

the class JavaMethodsConflictResolver method checkSpecifics.

public void checkSpecifics(@NotNull List<CandidateInfo> conflicts, @MethodCandidateInfo.ApplicabilityLevelConstant int applicabilityLevel, FactoryMap<MethodCandidateInfo, PsiSubstitutor> map, @NotNull LanguageLevel languageLevel) {
    final boolean applicable = applicabilityLevel > MethodCandidateInfo.ApplicabilityLevel.NOT_APPLICABLE;
    int conflictsCount = conflicts.size();
    // Specifics
    if (applicable) {
        final CandidateInfo[] newConflictsArray = conflicts.toArray(new CandidateInfo[conflicts.size()]);
        for (int i = 1; i < conflictsCount; i++) {
            final CandidateInfo method = newConflictsArray[i];
            for (int j = 0; j < i; j++) {
                ProgressManager.checkCanceled();
                final CandidateInfo conflict = newConflictsArray[j];
                if (nonComparable(method, conflict, applicabilityLevel == MethodCandidateInfo.ApplicabilityLevel.FIXED_ARITY))
                    continue;
                switch(isMoreSpecific((MethodCandidateInfo) method, (MethodCandidateInfo) conflict, applicabilityLevel, map, languageLevel)) {
                    case FIRST:
                        conflicts.remove(conflict);
                        break;
                    case SECOND:
                        conflicts.remove(method);
                        break;
                    case NEITHER:
                        break;
                }
            }
        }
    }
}
Also used : CandidateInfo(com.intellij.psi.infos.CandidateInfo) MethodCandidateInfo(com.intellij.psi.infos.MethodCandidateInfo)

Example 13 with MethodCandidateInfo

use of com.intellij.psi.infos.MethodCandidateInfo in project intellij-community by JetBrains.

the class JavaMethodsConflictResolver method checkAccessStaticLevels.

protected static void checkAccessStaticLevels(@NotNull List<CandidateInfo> conflicts, boolean checkAccessible) {
    int conflictsCount = conflicts.size();
    int maxCheckLevel = -1;
    int[] checkLevels = new int[conflictsCount];
    int index = 0;
    for (final CandidateInfo conflict : conflicts) {
        ProgressManager.checkCanceled();
        final MethodCandidateInfo method = (MethodCandidateInfo) conflict;
        final int level = checkAccessible ? getCheckAccessLevel(method) : getCheckStaticLevel(method);
        checkLevels[index++] = level;
        maxCheckLevel = Math.max(maxCheckLevel, level);
    }
    for (int i = conflictsCount - 1; i >= 0; i--) {
        // check for level
        if (checkLevels[i] < maxCheckLevel) {
            conflicts.remove(i);
        }
    }
}
Also used : MethodCandidateInfo(com.intellij.psi.infos.MethodCandidateInfo) CandidateInfo(com.intellij.psi.infos.CandidateInfo) MethodCandidateInfo(com.intellij.psi.infos.MethodCandidateInfo)

Example 14 with MethodCandidateInfo

use of com.intellij.psi.infos.MethodCandidateInfo in project intellij-community by JetBrains.

the class PsiMethodReferenceExpressionImpl method isAcceptable.

@Override
public boolean isAcceptable(PsiType left) {
    if (left instanceof PsiIntersectionType) {
        for (PsiType conjunct : ((PsiIntersectionType) left).getConjuncts()) {
            if (isAcceptable(conjunct))
                return true;
        }
        return false;
    }
    final PsiExpressionList argsList = PsiTreeUtil.getParentOfType(this, PsiExpressionList.class);
    final boolean isExact = isExact();
    if (MethodCandidateInfo.ourOverloadGuard.currentStack().contains(argsList)) {
        final MethodCandidateInfo.CurrentCandidateProperties candidateProperties = MethodCandidateInfo.getCurrentMethod(argsList);
        if (candidateProperties != null) {
            final PsiMethod method = candidateProperties.getMethod();
            if (isExact && !InferenceSession.isPertinentToApplicability(this, method)) {
                return true;
            }
            if (LambdaUtil.isPotentiallyCompatibleWithTypeParameter(this, argsList, method)) {
                return true;
            }
        }
    }
    left = FunctionalInterfaceParameterizationUtil.getGroundTargetType(left);
    if (!isPotentiallyCompatible(left)) {
        return false;
    }
    if (MethodCandidateInfo.ourOverloadGuard.currentStack().contains(argsList)) {
        if (!isExact) {
            return true;
        }
    }
    // A method reference is congruent with a function type if the following are true:
    //   The function type identifies a single compile-time declaration corresponding to the reference.
    //   One of the following is true:
    //      i)The return type of the function type is void.
    //     ii)The return type of the function type is R; 
    //        the result of applying capture conversion (5.1.10) to the return type of the invocation type (15.12.2.6) of the chosen declaration is R', 
    //        where R is the target type that may be used to infer R'; neither R nor R' is void; and R' is compatible with R in an assignment context.
    Map<PsiElement, PsiType> map = LambdaUtil.getFunctionalTypeMap();
    final JavaResolveResult result;
    try {
        if (map.put(this, left) != null) {
            return false;
        }
        result = advancedResolve(false);
    } finally {
        map.remove(this);
    }
    if (result instanceof MethodCandidateInfo && !((MethodCandidateInfo) result).isApplicable()) {
        return false;
    }
    final PsiElement resolve = result.getElement();
    if (resolve == null) {
        return false;
    }
    return PsiMethodReferenceUtil.isReturnTypeCompatible(this, result, left);
}
Also used : MethodCandidateInfo(com.intellij.psi.infos.MethodCandidateInfo) JavaStubPsiElement(com.intellij.psi.impl.source.JavaStubPsiElement)

Example 15 with MethodCandidateInfo

use of com.intellij.psi.infos.MethodCandidateInfo in project intellij-community by JetBrains.

the class Java8ExpressionsCheckTest method testCachingOfResultsDuringCandidatesIteration.

public void testCachingOfResultsDuringCandidatesIteration() throws Exception {
    configureByFile(BASE_PATH + "/" + getTestName(false) + ".java");
    final Collection<PsiMethodCallExpression> methodCallExpressions = PsiTreeUtil.findChildrenOfType(getFile(), PsiMethodCallExpression.class);
    final PsiResolveHelper helper = JavaPsiFacade.getInstance(getProject()).getResolveHelper();
    for (PsiMethodCallExpression expression : methodCallExpressions) {
        CandidateInfo[] candidates = helper.getReferencedMethodCandidates(expression, false, true);
        PsiExpressionList argumentList = expression.getArgumentList();
        PsiExpression[] args = argumentList.getExpressions();
        for (JavaResolveResult result : candidates) {
            if (result instanceof MethodCandidateInfo) {
                final MethodCandidateInfo info = (MethodCandidateInfo) result;
                MethodCandidateInfo.ourOverloadGuard.doPreventingRecursion(argumentList, false, () -> info.inferTypeArguments(DefaultParameterTypeInferencePolicy.INSTANCE, args, true));
            }
        }
        PsiMethodCallExpression parentCall = PsiTreeUtil.getParentOfType(expression, PsiMethodCallExpression.class, true);
        if (parentCall != null) {
            JavaResolveResult result = parentCall.getMethodExpression().advancedResolve(false);
            if (result instanceof MethodCandidateInfo) {
                assertNull(((MethodCandidateInfo) result).getInferenceErrorMessage());
            }
        }
    }
}
Also used : MethodCandidateInfo(com.intellij.psi.infos.MethodCandidateInfo) CandidateInfo(com.intellij.psi.infos.CandidateInfo) MethodCandidateInfo(com.intellij.psi.infos.MethodCandidateInfo)

Aggregations

MethodCandidateInfo (com.intellij.psi.infos.MethodCandidateInfo)27 CandidateInfo (com.intellij.psi.infos.CandidateInfo)12 HighlightInfo (com.intellij.codeInsight.daemon.impl.HighlightInfo)4 TextRange (com.intellij.openapi.util.TextRange)4 MethodParameterInfoHandler (com.intellij.codeInsight.hint.api.impls.MethodParameterInfoHandler)3 CreateParameterInfoContext (com.intellij.lang.parameterInfo.CreateParameterInfoContext)3 MockCreateParameterInfoContext (com.intellij.testFramework.utils.parameterInfo.MockCreateParameterInfoContext)3 Nullable (org.jetbrains.annotations.Nullable)3 HighlightInfoType (com.intellij.codeInsight.daemon.impl.HighlightInfoType)2 LocalQuickFixAndIntentionActionOnPsiElement (com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement)2 ParameterInfoUIContextEx (com.intellij.lang.parameterInfo.ParameterInfoUIContextEx)2 IndexNotReadyException (com.intellij.openapi.project.IndexNotReadyException)2 NotNull (org.jetbrains.annotations.NotNull)2 TextAttributesScheme (com.intellij.openapi.editor.colors.TextAttributesScheme)1 Pair (com.intellij.openapi.util.Pair)1 Ref (com.intellij.openapi.util.Ref)1 VirtualFile (com.intellij.openapi.vfs.VirtualFile)1 PsiElement (com.intellij.psi.PsiElement)1 JavaStubPsiElement (com.intellij.psi.impl.source.JavaStubPsiElement)1 ParameterTypeInferencePolicy (com.intellij.psi.impl.source.resolve.ParameterTypeInferencePolicy)1