Search in sources :

Example 31 with CandidateInfo

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

the class PsiDocParamRef method getReference.

@Override
public PsiReference getReference() {
    final PsiDocComment comment = PsiTreeUtil.getParentOfType(this, PsiDocComment.class);
    if (comment == null)
        return null;
    final PsiJavaDocumentedElement owner = comment.getOwner();
    if (!(owner instanceof PsiMethod) && !(owner instanceof PsiClass))
        return null;
    final ASTNode valueToken = findChildByType(JavaDocTokenType.DOC_TAG_VALUE_TOKEN);
    if (valueToken == null)
        return null;
    final String name = valueToken.getText();
    PsiElement reference = null;
    final PsiElement firstChild = getFirstChild();
    if (firstChild instanceof PsiDocToken && ((PsiDocToken) firstChild).getTokenType().equals(JavaDocTokenType.DOC_TAG_VALUE_LT)) {
        final PsiTypeParameter[] typeParameters = ((PsiTypeParameterListOwner) owner).getTypeParameters();
        for (PsiTypeParameter typeParameter : typeParameters) {
            if (typeParameter.getName().equals(name)) {
                reference = typeParameter;
            }
        }
    } else if (owner instanceof PsiMethod) {
        final PsiParameter[] parameters = ((PsiMethod) owner).getParameterList().getParameters();
        for (PsiParameter parameter : parameters) {
            if (parameter.getName().equals(name)) {
                reference = parameter;
            }
        }
    }
    final PsiElement resultReference = reference;
    return new PsiJavaReference() {

        @Override
        public PsiElement resolve() {
            return resultReference;
        }

        @Override
        @NotNull
        public String getCanonicalText() {
            return valueToken.getText();
        }

        @Override
        public PsiElement handleElementRename(String newElementName) {
            final CharTable charTableByTree = SharedImplUtil.findCharTableByTree(getNode());
            LeafElement newElement = Factory.createSingleLeafElement(JavaDocTokenType.DOC_TAG_VALUE_TOKEN, newElementName, charTableByTree, getManager());
            replaceChild(valueToken, newElement);
            return PsiDocParamRef.this;
        }

        @Override
        public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
            if (isReferenceTo(element))
                return PsiDocParamRef.this;
            if (!(element instanceof PsiParameter)) {
                throw new IncorrectOperationException("Unsupported operation");
            }
            return handleElementRename(((PsiParameter) element).getName());
        }

        @Override
        public boolean isReferenceTo(PsiElement element) {
            if (!(element instanceof PsiNamedElement))
                return false;
            PsiNamedElement namedElement = (PsiNamedElement) element;
            if (!getCanonicalText().equals(namedElement.getName()))
                return false;
            return getManager().areElementsEquivalent(resolve(), element);
        }

        @Override
        @NotNull
        public PsiElement[] getVariants() {
            final PsiElement firstChild = getFirstChild();
            Set<String> usedNames = new HashSet<>();
            for (PsiDocTag tag : comment.getTags()) {
                if (tag.getName().equals("param")) {
                    PsiDocTagValue valueElement = tag.getValueElement();
                    if (valueElement != null) {
                        usedNames.add(valueElement.getText());
                    }
                }
            }
            PsiNamedElement[] result = PsiNamedElement.EMPTY_ARRAY;
            if (firstChild instanceof PsiDocToken && ((PsiDocToken) firstChild).getTokenType().equals(JavaDocTokenType.DOC_TAG_VALUE_LT)) {
                result = ((PsiTypeParameterListOwner) owner).getTypeParameters();
            } else if (owner instanceof PsiMethod) {
                result = ((PsiMethod) owner).getParameterList().getParameters();
            }
            List<PsiElement> filtered = new ArrayList<>();
            for (PsiNamedElement namedElement : result) {
                if (!usedNames.contains(namedElement.getName())) {
                    filtered.add(namedElement);
                }
            }
            return filtered.toArray(new PsiElement[filtered.size()]);
        }

        @Override
        public boolean isSoft() {
            return false;
        }

        @Override
        public TextRange getRangeInElement() {
            final int startOffsetInParent = valueToken.getPsi().getStartOffsetInParent();
            return new TextRange(startOffsetInParent, startOffsetInParent + valueToken.getTextLength());
        }

        @Override
        public PsiElement getElement() {
            return PsiDocParamRef.this;
        }

        @Override
        public void processVariants(@NotNull PsiScopeProcessor processor) {
            for (final PsiElement element : getVariants()) {
                if (!processor.execute(element, ResolveState.initial())) {
                    return;
                }
            }
        }

        @Override
        @NotNull
        public JavaResolveResult advancedResolve(boolean incompleteCode) {
            return resultReference == null ? JavaResolveResult.EMPTY : new CandidateInfo(resultReference, PsiSubstitutor.EMPTY);
        }

        @Override
        @NotNull
        public JavaResolveResult[] multiResolve(boolean incompleteCode) {
            return resultReference == null ? JavaResolveResult.EMPTY_ARRAY : new JavaResolveResult[] { new CandidateInfo(resultReference, PsiSubstitutor.EMPTY) };
        }
    };
}
Also used : PsiDocTag(com.intellij.psi.javadoc.PsiDocTag) CandidateInfo(com.intellij.psi.infos.CandidateInfo) ArrayList(java.util.ArrayList) PsiDocToken(com.intellij.psi.javadoc.PsiDocToken) PsiScopeProcessor(com.intellij.psi.scope.PsiScopeProcessor) CharTable(com.intellij.util.CharTable) NotNull(org.jetbrains.annotations.NotNull) ASTNode(com.intellij.lang.ASTNode) HashSet(java.util.HashSet) PsiDocComment(com.intellij.psi.javadoc.PsiDocComment) TextRange(com.intellij.openapi.util.TextRange) PsiDocTagValue(com.intellij.psi.javadoc.PsiDocTagValue) IncorrectOperationException(com.intellij.util.IncorrectOperationException)

Example 32 with CandidateInfo

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

the class MethodCallFixer method getUnambiguousParameterCount.

@Nullable
private static Integer getUnambiguousParameterCount(PsiCallExpression call) {
    int argCount = -1;
    for (CandidateInfo candidate : PsiResolveHelper.SERVICE.getInstance(call.getProject()).getReferencedMethodCandidates(call, false)) {
        PsiElement element = candidate.getElement();
        if (!(element instanceof PsiMethod))
            return null;
        if (((PsiMethod) element).isVarArgs())
            return null;
        int count = ((PsiMethod) element).getParameterList().getParametersCount();
        if (argCount == -1) {
            argCount = count;
        } else if (argCount != count) {
            return null;
        }
    }
    return argCount;
}
Also used : CandidateInfo(com.intellij.psi.infos.CandidateInfo) Nullable(org.jetbrains.annotations.Nullable)

Example 33 with CandidateInfo

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

the class PsiMethodWithOverridingPercentMember method calculateOverridingPercents.

@NotNull
public static PsiMethodWithOverridingPercentMember[] calculateOverridingPercents(@NotNull final Collection<CandidateInfo> candidateInfos) {
    final List<PsiMethodWithOverridingPercentMember> result = new ArrayList<>(candidateInfos.size());
    final Map<String, Collection<PsiClass>> classShortNames2Inheritors = new HashMap<>();
    for (final CandidateInfo candidateInfo : candidateInfos) {
        final PsiMethod method = (PsiMethod) candidateInfo.getElement();
        if (!method.hasModifierProperty(PsiModifier.FINAL) && !method.isConstructor() && !method.isDeprecated() && !EXCLUDED_JAVA_LANG_OBJECT_METHOD_NAMES.contains(method.getName())) {
            final PsiClass containingClass = method.getContainingClass();
            if (containingClass == null) {
                continue;
            }
            final String classShortName = containingClass.getName();
            Collection<PsiClass> allInheritors = classShortNames2Inheritors.get(classShortName);
            if (allInheritors == null) {
                allInheritors = ClassInheritorsSearch.search(containingClass).findAll();
                classShortNames2Inheritors.put(classShortName, allInheritors);
            }
            final int allInheritorsCount = allInheritors.size() - 1;
            if (allInheritorsCount > 0) {
                final int percent = searchForOverridingCount(method, allInheritors) * 100 / allInheritorsCount;
                if (percent > 1) {
                    result.add(new PsiMethodWithOverridingPercentMember(candidateInfo, percent));
                }
            }
        }
    }
    return result.toArray(new PsiMethodWithOverridingPercentMember[result.size()]);
}
Also used : CandidateInfo(com.intellij.psi.infos.CandidateInfo) NotNull(org.jetbrains.annotations.NotNull)

Example 34 with CandidateInfo

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

the class MethodParameterInfoHandler method updateParameterInfo.

@Override
public void updateParameterInfo(@NotNull final PsiExpressionList o, @NotNull final UpdateParameterInfoContext context) {
    PsiElement parameterOwner = context.getParameterOwner();
    if (parameterOwner != o) {
        context.removeHint();
        return;
    }
    int index = ParameterInfoUtils.getCurrentParameterIndex(o.getNode(), context.getOffset(), JavaTokenType.COMMA);
    context.setCurrentParameter(index);
    Object[] candidates = context.getObjectsToView();
    PsiExpression[] args = o.getExpressions();
    PsiCall call = getCall(o);
    PsiElement realResolve = call != null ? call.resolveMethod() : null;
    PsiMethod chosenMethod = CompletionMemory.getChosenMethod(call);
    CandidateInfo chosenInfo = null;
    CandidateInfo completeMatch = null;
    for (int i = 0; i < candidates.length; i++) {
        CandidateInfo candidate = (CandidateInfo) candidates[i];
        PsiMethod method = (PsiMethod) candidate.getElement();
        if (!method.isValid())
            continue;
        PsiSubstitutor substitutor = getCandidateInfoSubstitutor(candidate);
        assert substitutor != null;
        if (!method.isValid() || !substitutor.isValid()) {
            // this may sometimes happen e,g, when editing method call in field initializer candidates in the same file get invalidated
            context.setUIComponentEnabled(i, false);
            continue;
        }
        PsiParameter[] parms = method.getParameterList().getParameters();
        boolean enabled = true;
        if (parms.length <= index) {
            if (parms.length > 0) {
                if (method.isVarArgs()) {
                    for (int j = 0; j < parms.length - 1; j++) {
                        PsiType parmType = substitutor.substitute(parms[j].getType());
                        PsiType argType = args[j].getType();
                        if (argType != null && !parmType.isAssignableFrom(argType)) {
                            enabled = false;
                            break;
                        }
                    }
                    if (enabled) {
                        PsiArrayType lastParmType = (PsiArrayType) substitutor.substitute(parms[parms.length - 1].getType());
                        PsiType componentType = lastParmType.getComponentType();
                        if (parms.length == args.length) {
                            PsiType lastArgType = args[args.length - 1].getType();
                            if (lastArgType != null && !lastParmType.isAssignableFrom(lastArgType) && !componentType.isAssignableFrom(lastArgType)) {
                                enabled = false;
                            }
                        } else {
                            for (int j = parms.length; j <= index && j < args.length; j++) {
                                PsiExpression arg = args[j];
                                PsiType argType = arg.getType();
                                if (argType != null && !componentType.isAssignableFrom(argType)) {
                                    enabled = false;
                                    break;
                                }
                            }
                        }
                    }
                } else {
                    enabled = false;
                }
            } else {
                enabled = index == 0;
            }
        } else {
            enabled = isAssignableParametersBeforeGivenIndex(parms, args, index, substitutor);
        }
        context.setUIComponentEnabled(i, enabled);
        if (candidates.length > 1 && enabled) {
            if (chosenMethod == method) {
                chosenInfo = candidate;
            }
            if (parms.length == args.length && realResolve == method && isAssignableParametersBeforeGivenIndex(parms, args, args.length, substitutor)) {
                completeMatch = candidate;
            }
        }
    }
    if (chosenInfo != null) {
        context.setHighlightedParameter(chosenInfo);
    } else if (completeMatch != null) {
        context.setHighlightedParameter(completeMatch);
    }
}
Also used : CandidateInfo(com.intellij.psi.infos.CandidateInfo) MethodCandidateInfo(com.intellij.psi.infos.MethodCandidateInfo)

Example 35 with CandidateInfo

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

the class MethodParameterInfoHandler method getCandidates.

private static CandidateInfo[] getCandidates(PsiCallExpression call) {
    final MethodCandidatesProcessor processor = new MethodResolverProcessor(call, call.getContainingFile(), new PsiConflictResolver[0]) {

        @Override
        protected boolean acceptVarargs() {
            return false;
        }
    };
    try {
        PsiScopesUtil.setupAndRunProcessor(processor, call, true);
    } catch (MethodProcessorSetupFailedException e) {
        return CandidateInfo.EMPTY_ARRAY;
    }
    final List<CandidateInfo> results = processor.getResults();
    return results.toArray(new CandidateInfo[results.size()]);
}
Also used : MethodCandidatesProcessor(com.intellij.psi.scope.processor.MethodCandidatesProcessor) CandidateInfo(com.intellij.psi.infos.CandidateInfo) MethodCandidateInfo(com.intellij.psi.infos.MethodCandidateInfo) MethodResolverProcessor(com.intellij.psi.scope.processor.MethodResolverProcessor) MethodProcessorSetupFailedException(com.intellij.psi.scope.MethodProcessorSetupFailedException)

Aggregations

CandidateInfo (com.intellij.psi.infos.CandidateInfo)60 MethodCandidateInfo (com.intellij.psi.infos.MethodCandidateInfo)19 NotNull (org.jetbrains.annotations.NotNull)13 Nullable (org.jetbrains.annotations.Nullable)6 Pair (com.intellij.openapi.util.Pair)4 ArrayList (java.util.ArrayList)4 HashSet (java.util.HashSet)4 GrModifierList (org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList)4 Project (com.intellij.openapi.project.Project)3 TextRange (com.intellij.openapi.util.TextRange)3 PsiClass (com.intellij.psi.PsiClass)3 PsiElement (com.intellij.psi.PsiElement)3 IncorrectOperationException (com.intellij.util.IncorrectOperationException)3 GrReferenceList (org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrReferenceList)3 PsiMethodMember (com.intellij.codeInsight.generation.PsiMethodMember)2 Result (com.intellij.openapi.application.Result)2 WriteCommandAction (com.intellij.openapi.command.WriteCommandAction)2 LanguageLevel (com.intellij.pom.java.LanguageLevel)2 ClassCandidateInfo (com.intellij.psi.infos.ClassCandidateInfo)2 PsiScopeProcessor (com.intellij.psi.scope.PsiScopeProcessor)2