Search in sources :

Example 1 with ClassCandidateInfo

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

the class JavaClassReference method advancedResolveInner.

private JavaResolveResult advancedResolveInner(@NotNull PsiElement psiElement, @NotNull String qName, @NotNull PsiFile containingFile) {
    final PsiManager manager = containingFile.getManager();
    final GlobalSearchScope scope = getScope(containingFile);
    if (myIndex == myJavaClassReferenceSet.getReferences().length - 1) {
        final PsiClass aClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(qName, scope);
        if (aClass != null) {
            return new ClassCandidateInfo(aClass, PsiSubstitutor.EMPTY, false, psiElement);
        } else {
            if (!JavaClassReferenceProvider.ADVANCED_RESOLVE.getBooleanValue(getOptions())) {
                return JavaResolveResult.EMPTY;
            }
        }
    }
    PsiElement resolveResult = JavaPsiFacade.getInstance(manager.getProject()).findPackage(qName);
    if (resolveResult == null) {
        resolveResult = JavaPsiFacade.getInstance(manager.getProject()).findClass(qName, scope);
    }
    if (myInStaticImport && resolveResult == null) {
        resolveResult = resolveMember(qName, manager, getElement().getResolveScope());
    }
    if (resolveResult == null) {
        if (containingFile instanceof PsiJavaFile) {
            if (containingFile instanceof ServerPageFile) {
                containingFile = containingFile.getViewProvider().getPsi(JavaLanguage.INSTANCE);
                if (containingFile == null)
                    return JavaResolveResult.EMPTY;
            }
            final ClassResolverProcessor processor = new ClassResolverProcessor(getCanonicalText(), psiElement, containingFile);
            PsiClass contextClass = myJavaClassReferenceSet.getProvider().getContextClass(psiElement);
            if (contextClass != null) {
                PsiScopesUtil.treeWalkUp(processor, contextClass, null);
            } else {
                containingFile.processDeclarations(processor, ResolveState.initial(), null, psiElement);
            }
            if (processor.getResult().length == 1) {
                final JavaResolveResult javaResolveResult = processor.getResult()[0];
                if (javaResolveResult != JavaResolveResult.EMPTY && getOptions() != null) {
                    final Boolean value = JavaClassReferenceProvider.RESOLVE_QUALIFIED_CLASS_NAME.getValue(getOptions());
                    final PsiClass psiClass = (PsiClass) javaResolveResult.getElement();
                    if (value != null && value.booleanValue() && psiClass != null) {
                        final String qualifiedName = psiClass.getQualifiedName();
                        if (!qName.equals(qualifiedName)) {
                            return JavaResolveResult.EMPTY;
                        }
                    }
                }
                return javaResolveResult;
            }
        }
    }
    return resolveResult != null ? new CandidateInfo(resolveResult, PsiSubstitutor.EMPTY, false, false, psiElement) : JavaResolveResult.EMPTY;
}
Also used : ClassResolverProcessor(com.intellij.psi.impl.source.resolve.ClassResolverProcessor) GlobalSearchScope(com.intellij.psi.search.GlobalSearchScope) ClassCandidateInfo(com.intellij.psi.infos.ClassCandidateInfo) CandidateInfo(com.intellij.psi.infos.CandidateInfo) ClassCandidateInfo(com.intellij.psi.infos.ClassCandidateInfo)

Example 2 with ClassCandidateInfo

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

the class PsiScopesUtil method setupAndRunProcessor.

public static void setupAndRunProcessor(@NotNull MethodsProcessor processor, @NotNull PsiCallExpression call, boolean dummyImplicitConstructor) throws MethodProcessorSetupFailedException {
    if (call instanceof PsiMethodCallExpression) {
        final PsiMethodCallExpression methodCall = (PsiMethodCallExpression) call;
        final PsiJavaCodeReferenceElement ref = methodCall.getMethodExpression();
        processor.setArgumentList(methodCall.getArgumentList());
        processor.obtainTypeArguments(methodCall);
        if (!ref.isQualified() || ref.getReferenceNameElement() instanceof PsiKeyword) {
            final PsiElement referenceNameElement = ref.getReferenceNameElement();
            if (referenceNameElement == null)
                return;
            if (referenceNameElement instanceof PsiKeyword) {
                final PsiKeyword keyword = (PsiKeyword) referenceNameElement;
                if (keyword.getTokenType() == JavaTokenType.THIS_KEYWORD) {
                    final PsiClass aClass = JavaResolveUtil.getContextClass(methodCall);
                    if (aClass == null) {
                        throw new MethodProcessorSetupFailedException("Can't resolve class for this expression");
                    }
                    processor.setIsConstructor(true);
                    processor.setAccessClass(aClass);
                    aClass.processDeclarations(processor, ResolveState.initial(), null, call);
                    if (dummyImplicitConstructor) {
                        processDummyConstructor(processor, aClass);
                    }
                } else if (keyword.getTokenType() == JavaTokenType.SUPER_KEYWORD) {
                    PsiClass aClass = JavaResolveUtil.getContextClass(methodCall);
                    if (aClass == null) {
                        throw new MethodProcessorSetupFailedException("Can't resolve class for super expression");
                    }
                    final PsiClass superClass = aClass.getSuperClass();
                    if (superClass != null) {
                        PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
                        PsiClass runSuper = superClass;
                        List<PsiSubstitutor> contextSubstitutors = new ArrayList<>();
                        do {
                            if (runSuper != null) {
                                PsiSubstitutor superSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(runSuper, aClass, PsiSubstitutor.EMPTY);
                                contextSubstitutors.add(superSubstitutor);
                            }
                            if (aClass.hasModifierProperty(PsiModifier.STATIC))
                                break;
                            aClass = JavaResolveUtil.getContextClass(aClass);
                            if (aClass != null)
                                runSuper = aClass.getSuperClass();
                        } while (aClass != null);
                        //apply substitutors in 'outer classes down to inner classes' order because inner class subst take precedence
                        for (int i = contextSubstitutors.size() - 1; i >= 0; i--) {
                            PsiSubstitutor contextSubstitutor = contextSubstitutors.get(i);
                            substitutor = substitutor.putAll(contextSubstitutor);
                        }
                        processor.setIsConstructor(true);
                        processor.setAccessClass(null);
                        final PsiMethod[] constructors = superClass.getConstructors();
                        ResolveState state = ResolveState.initial().put(PsiSubstitutor.KEY, substitutor);
                        for (PsiMethod constructor : constructors) {
                            if (!processor.execute(constructor, state))
                                return;
                        }
                        if (dummyImplicitConstructor)
                            processDummyConstructor(processor, superClass);
                    }
                } else {
                    LOG.error("Unknown name element " + referenceNameElement + " in reference " + ref.getText() + "(" + ref + ")");
                }
            } else if (referenceNameElement instanceof PsiIdentifier) {
                processor.setIsConstructor(false);
                processor.setName(referenceNameElement.getText());
                processor.setAccessClass(null);
                resolveAndWalk(processor, ref, null);
            } else {
                LOG.error("Unknown name element " + referenceNameElement + " in reference " + ref.getText() + "(" + ref + ")");
            }
        } else {
            // Complex expression
            final PsiElement referenceName = methodCall.getMethodExpression().getReferenceNameElement();
            final PsiManager manager = call.getManager();
            final PsiElement qualifier = ref.getQualifier();
            if (referenceName == null) {
                // e.g. "manager.(beginTransaction)"
                throw new MethodProcessorSetupFailedException("Can't resolve method name for this expression");
            }
            if (referenceName instanceof PsiIdentifier && qualifier instanceof PsiExpression) {
                PsiType type = ((PsiExpression) qualifier).getType();
                if (type != null && qualifier instanceof PsiReferenceExpression) {
                    final PsiElement resolve = ((PsiReferenceExpression) qualifier).resolve();
                    if (resolve instanceof PsiEnumConstant) {
                        final PsiEnumConstantInitializer initializingClass = ((PsiEnumConstant) resolve).getInitializingClass();
                        if (hasDesiredMethod(methodCall, type, initializingClass)) {
                            processQualifierResult(new ClassCandidateInfo(initializingClass, PsiSubstitutor.EMPTY), processor, methodCall);
                            return;
                        }
                    } else if (resolve instanceof PsiVariable && ((PsiVariable) resolve).hasModifierProperty(PsiModifier.FINAL) && ((PsiVariable) resolve).hasInitializer()) {
                        final PsiExpression initializer = ((PsiVariable) resolve).getInitializer();
                        if (initializer instanceof PsiNewExpression) {
                            final PsiAnonymousClass anonymousClass = ((PsiNewExpression) initializer).getAnonymousClass();
                            if (hasDesiredMethod(methodCall, type, anonymousClass)) {
                                type = initializer.getType();
                            }
                        }
                    }
                }
                if (type == null) {
                    if (qualifier instanceof PsiJavaCodeReferenceElement) {
                        final JavaResolveResult result = ((PsiJavaCodeReferenceElement) qualifier).advancedResolve(false);
                        if (result.getElement() instanceof PsiClass) {
                            processor.handleEvent(JavaScopeProcessorEvent.START_STATIC, null);
                            processQualifierResult(result, processor, methodCall);
                        }
                    } else {
                        throw new MethodProcessorSetupFailedException("Cant determine qualifier type!");
                    }
                } else if (type instanceof PsiDisjunctionType) {
                    processQualifierType(((PsiDisjunctionType) type).getLeastUpperBound(), processor, manager, methodCall);
                } else if (type instanceof PsiCapturedWildcardType) {
                    final PsiType psiType = convertToTypeParameter((PsiCapturedWildcardType) type, methodCall);
                    if (psiType != null) {
                        processQualifierType(psiType, processor, manager, methodCall);
                    }
                } else {
                    processQualifierType(type, processor, manager, methodCall);
                }
            } else {
                LOG.error("ref: " + ref + " (" + ref.getClass() + ")," + " ref.getReferenceNameElement()=" + ref.getReferenceNameElement() + "; methodCall.getMethodExpression().getReferenceNameElement()=" + methodCall.getMethodExpression().getReferenceNameElement() + "; qualifier=" + qualifier);
            }
        }
    } else {
        LOG.assertTrue(call instanceof PsiNewExpression);
        PsiNewExpression newExpr = (PsiNewExpression) call;
        PsiJavaCodeReferenceElement classRef = newExpr.getClassOrAnonymousClassReference();
        if (classRef == null) {
            throw new MethodProcessorSetupFailedException("Cant get reference to class in new expression");
        }
        final JavaResolveResult result = classRef.advancedResolve(false);
        PsiClass aClass = (PsiClass) result.getElement();
        if (aClass == null) {
            throw new MethodProcessorSetupFailedException("Cant resolve class in new expression");
        }
        processor.setIsConstructor(true);
        processor.setAccessClass(aClass);
        processor.setArgumentList(newExpr.getArgumentList());
        processor.obtainTypeArguments(newExpr);
        aClass.processDeclarations(processor, ResolveState.initial().put(PsiSubstitutor.KEY, result.getSubstitutor()), null, call);
        if (dummyImplicitConstructor) {
            processDummyConstructor(processor, aClass);
        }
    }
}
Also used : ArrayList(java.util.ArrayList) List(java.util.List) ClassCandidateInfo(com.intellij.psi.infos.ClassCandidateInfo) MethodProcessorSetupFailedException(com.intellij.psi.scope.MethodProcessorSetupFailedException)

Example 3 with ClassCandidateInfo

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

the class ClassResolverProcessor method execute.

@Override
public boolean execute(@NotNull PsiElement element, @NotNull ResolveState state) {
    if (!(element instanceof PsiClass))
        return true;
    final PsiClass aClass = (PsiClass) element;
    final String name = aClass.getName();
    if (!myClassName.equals(name)) {
        return true;
    }
    boolean accessible = myPlace == null || checkAccessibility(aClass);
    if (myCandidates == null) {
        myCandidates = new SmartList<>();
    } else {
        String fqName = aClass.getQualifiedName();
        if (fqName != null) {
            for (int i = myCandidates.size() - 1; i >= 0; i--) {
                ClassCandidateInfo info = myCandidates.get(i);
                Domination domination = dominates(aClass, accessible && isAccessible(aClass), fqName, info);
                if (domination == Domination.DOMINATED_BY) {
                    return true;
                } else if (domination == Domination.DOMINATES) {
                    myCandidates.remove(i);
                }
            }
        }
    }
    myHasAccessibleCandidate |= accessible;
    myHasInaccessibleCandidate |= !accessible;
    myCandidates.add(new ClassCandidateInfo(aClass, state.get(PsiSubstitutor.KEY), !accessible, myCurrentFileContext));
    myResult = null;
    if (!accessible)
        return true;
    if (aClass.hasModifierProperty(PsiModifier.PRIVATE)) {
        final PsiClass containingPlaceClass = PsiTreeUtil.getParentOfType(myPlace, PsiClass.class, false);
        if (containingPlaceClass != null && !PsiTreeUtil.isAncestor(containingPlaceClass, aClass, false)) {
            return true;
        }
    }
    return myCurrentFileContext instanceof PsiImportStatementBase;
}
Also used : ClassCandidateInfo(com.intellij.psi.infos.ClassCandidateInfo)

Example 4 with ClassCandidateInfo

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

the class MethodReferenceResolver method resolve.

@NotNull
@Override
public JavaResolveResult[] resolve(@NotNull final PsiMethodReferenceExpressionImpl reference, @NotNull final PsiFile containingFile, boolean incompleteCode) {
    final PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult(reference);
    final PsiClass containingClass = qualifierResolveResult.getContainingClass();
    PsiSubstitutor substitutor = qualifierResolveResult.getSubstitutor();
    if (containingClass != null) {
        final PsiElement element = reference.getReferenceNameElement();
        final boolean isConstructor = reference.isConstructor();
        if (element instanceof PsiIdentifier || isConstructor) {
            if (isConstructor && !canBeConstructed(containingClass)) {
                return JavaResolveResult.EMPTY_ARRAY;
            }
            final PsiType functionalInterfaceType = getInterfaceType(reference);
            final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
            final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult);
            final PsiSubstitutor functionalInterfaceSubstitutor = interfaceMethod != null ? LambdaUtil.getSubstitutor(interfaceMethod, resolveResult) : null;
            final MethodSignature signature = interfaceMethod != null ? interfaceMethod.getSignature(functionalInterfaceSubstitutor) : null;
            final PsiType interfaceMethodReturnType = LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType);
            if (isConstructor && containingClass.getConstructors().length == 0) {
                if (interfaceMethod != null) {
                    final PsiClassType returnType = composeReturnType(containingClass, substitutor);
                    final InferenceSession session = new InferenceSession(containingClass.getTypeParameters(), substitutor, reference.getManager(), null);
                    if (!(session.isProperType(session.substituteWithInferenceVariables(returnType)) && session.isProperType(interfaceMethodReturnType))) {
                        session.registerReturnTypeConstraints(returnType, interfaceMethodReturnType);
                        substitutor = session.infer();
                    }
                }
                ClassCandidateInfo candidateInfo = null;
                final boolean isArray = PsiEquivalenceUtil.areElementsEquivalent(containingClass, JavaPsiFacade.getElementFactory(reference.getProject()).getArrayClass(PsiUtil.getLanguageLevel(reference)));
                if (signature == null || !isArray && (containingClass.getContainingClass() == null || !isLocatedInStaticContext(containingClass, reference)) && signature.getParameterTypes().length == 0 || isArray && arrayCreationSignature(signature)) {
                    candidateInfo = new ClassCandidateInfo(containingClass, substitutor);
                }
                return candidateInfo == null ? JavaResolveResult.EMPTY_ARRAY : new JavaResolveResult[] { candidateInfo };
            }
            final PsiConflictResolver conflictResolver = createResolver(reference, qualifierResolveResult, interfaceMethod, signature);
            final MethodCandidatesProcessor processor = new MethodCandidatesProcessor(reference, containingFile, new PsiConflictResolver[] { conflictResolver }, new SmartList<>()) {

                @Override
                protected boolean acceptVarargs() {
                    return true;
                }

                @Override
                protected MethodCandidateInfo createCandidateInfo(@NotNull final PsiMethod method, @NotNull final PsiSubstitutor substitutor, final boolean staticProblem, final boolean accessible, final boolean varargs) {
                    final PsiExpressionList argumentList = getArgumentList();
                    final PsiType[] typeParameters = reference.getTypeParameters();
                    return new MethodCandidateInfo(method, substitutor, !accessible, staticProblem, argumentList, myCurrentFileContext, argumentList != null ? argumentList.getExpressionTypes() : null, method.hasTypeParameters() && typeParameters.length > 0 ? typeParameters : null, getLanguageLevel()) {

                        @Override
                        public boolean isVarargs() {
                            return varargs;
                        }

                        @NotNull
                        @Override
                        public PsiSubstitutor inferTypeArguments(@NotNull ParameterTypeInferencePolicy policy, boolean includeReturnConstraint) {
                            return inferTypeArguments(includeReturnConstraint);
                        }

                        private PsiSubstitutor inferTypeArguments(boolean includeReturnConstraint) {
                            if (interfaceMethod == null)
                                return substitutor;
                            final InferenceSession session = new InferenceSession(method.getTypeParameters(), substitutor, reference.getManager(), reference);
                            session.initThrowsConstraints(method);
                            final PsiSubstitutor psiSubstitutor = session.collectApplicabilityConstraints(reference, this, functionalInterfaceType);
                            if (psiSubstitutor != null) {
                                return psiSubstitutor;
                            }
                            if (!session.repeatInferencePhases()) {
                                return substitutor;
                            }
                            if (includeReturnConstraint && !PsiType.VOID.equals(interfaceMethodReturnType) && interfaceMethodReturnType != null) {
                                PsiSubstitutor subst = PsiMethodReferenceCompatibilityConstraint.getSubstitutor(signature, qualifierResolveResult, method, containingClass, reference);
                                final PsiType returnType = method.isConstructor() ? composeReturnType(containingClass, subst) : subst.substitute(method.getReturnType());
                                if (returnType != null) {
                                    session.registerReturnTypeConstraints(returnType, interfaceMethodReturnType);
                                }
                            }
                            return session.infer(method.getParameterList().getParameters(), null, null);
                        }

                        @Override
                        public boolean isApplicable() {
                            if (signature == null)
                                return false;
                            final PsiType[] argTypes = signature.getParameterTypes();
                            boolean hasReceiver = PsiMethodReferenceUtil.isSecondSearchPossible(argTypes, qualifierResolveResult, reference);
                            return MethodReferenceConflictResolver.isApplicableByFirstSearch(this, argTypes, hasReceiver, reference, interfaceMethod.isVarArgs()) != null;
                        }
                    };
                }
            };
            processor.setIsConstructor(isConstructor);
            processor.setName(isConstructor ? containingClass.getName() : element.getText());
            final PsiExpression expression = reference.getQualifierExpression();
            if (expression == null || !(expression.getType() instanceof PsiArrayType)) {
                processor.setAccessClass(containingClass);
            }
            if (qualifierResolveResult.isReferenceTypeQualified() && isLocatedInStaticContext(containingClass, reference)) {
                processor.handleEvent(JavaScopeProcessorEvent.START_STATIC, null);
            }
            ResolveState state = ResolveState.initial().put(PsiSubstitutor.KEY, substitutor);
            containingClass.processDeclarations(processor, state, reference, reference);
            return processor.getResult();
        }
    }
    return JavaResolveResult.EMPTY_ARRAY;
}
Also used : NotNull(org.jetbrains.annotations.NotNull) PsiConflictResolver(com.intellij.psi.scope.PsiConflictResolver) MethodCandidateInfo(com.intellij.psi.infos.MethodCandidateInfo) ClassCandidateInfo(com.intellij.psi.infos.ClassCandidateInfo) MethodCandidatesProcessor(com.intellij.psi.scope.processor.MethodCandidatesProcessor) MethodSignature(com.intellij.psi.util.MethodSignature) InferenceSession(com.intellij.psi.impl.source.resolve.graphInference.InferenceSession) ParameterTypeInferencePolicy(com.intellij.psi.impl.source.resolve.ParameterTypeInferencePolicy) NotNull(org.jetbrains.annotations.NotNull)

Example 5 with ClassCandidateInfo

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

the class JavaClassReference method doAdvancedResolve.

@NotNull
private JavaResolveResult doAdvancedResolve(@NotNull PsiFile containingFile) {
    final PsiElement psiElement = getElement();
    if (!psiElement.isValid())
        return JavaResolveResult.EMPTY;
    final String elementText = psiElement.getText();
    final PsiElement context = getContext();
    if (context instanceof PsiClass) {
        if (isStaticClassReference(elementText, false)) {
            final PsiClass psiClass = ((PsiClass) context).findInnerClassByName(getCanonicalText(), false);
            if (psiClass != null) {
                return new ClassCandidateInfo(psiClass, PsiSubstitutor.EMPTY, false, psiElement);
            }
            PsiElement member = doResolveMember((PsiClass) context, myText);
            return member == null ? JavaResolveResult.EMPTY : new CandidateInfo(member, PsiSubstitutor.EMPTY, false, false, psiElement);
        } else if (!myInStaticImport && myJavaClassReferenceSet.isAllowDollarInNames()) {
            return JavaResolveResult.EMPTY;
        }
    }
    final int endOffset = getRangeInElement().getEndOffset();
    LOG.assertTrue(endOffset <= elementText.length(), elementText);
    final int startOffset = myJavaClassReferenceSet.getReference(0).getRangeInElement().getStartOffset();
    final String qName = elementText.substring(startOffset, endOffset);
    if (!qName.contains(".")) {
        final String defaultPackage = JavaClassReferenceProvider.DEFAULT_PACKAGE.getValue(getOptions());
        if (StringUtil.isNotEmpty(defaultPackage)) {
            final JavaResolveResult resolveResult = advancedResolveInner(psiElement, defaultPackage + "." + qName, containingFile);
            if (resolveResult != JavaResolveResult.EMPTY) {
                return resolveResult;
            }
        }
    }
    return advancedResolveInner(psiElement, qName, containingFile);
}
Also used : ClassCandidateInfo(com.intellij.psi.infos.ClassCandidateInfo) CandidateInfo(com.intellij.psi.infos.CandidateInfo) ClassCandidateInfo(com.intellij.psi.infos.ClassCandidateInfo) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

ClassCandidateInfo (com.intellij.psi.infos.ClassCandidateInfo)5 CandidateInfo (com.intellij.psi.infos.CandidateInfo)2 NotNull (org.jetbrains.annotations.NotNull)2 ClassResolverProcessor (com.intellij.psi.impl.source.resolve.ClassResolverProcessor)1 ParameterTypeInferencePolicy (com.intellij.psi.impl.source.resolve.ParameterTypeInferencePolicy)1 InferenceSession (com.intellij.psi.impl.source.resolve.graphInference.InferenceSession)1 MethodCandidateInfo (com.intellij.psi.infos.MethodCandidateInfo)1 MethodProcessorSetupFailedException (com.intellij.psi.scope.MethodProcessorSetupFailedException)1 PsiConflictResolver (com.intellij.psi.scope.PsiConflictResolver)1 MethodCandidatesProcessor (com.intellij.psi.scope.processor.MethodCandidatesProcessor)1 GlobalSearchScope (com.intellij.psi.search.GlobalSearchScope)1 MethodSignature (com.intellij.psi.util.MethodSignature)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1