| /* |
| * Copyright 2000-2014 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.intellij.psi.scope.processor; |
| |
| import com.intellij.psi.*; |
| import com.intellij.psi.impl.source.resolve.JavaResolveUtil; |
| import com.intellij.psi.infos.CandidateInfo; |
| import com.intellij.psi.infos.MethodCandidateInfo; |
| import com.intellij.psi.scope.PsiConflictResolver; |
| import com.intellij.psi.scope.conflictResolvers.DuplicateConflictResolver; |
| import com.intellij.psi.util.PsiUtil; |
| import com.intellij.util.SmartList; |
| import org.jetbrains.annotations.NotNull; |
| |
| import java.util.List; |
| |
| /** |
| * @author ik |
| * Date: 31.01.2003 |
| */ |
| public class MethodCandidatesProcessor extends MethodsProcessor{ |
| protected boolean myHasAccessibleStaticCorrectCandidate = false; |
| |
| public MethodCandidatesProcessor(@NotNull PsiElement place, PsiFile placeFile, @NotNull PsiConflictResolver[] resolvers, @NotNull List<CandidateInfo> container) { |
| super(resolvers, container, place, placeFile); |
| } |
| |
| public MethodCandidatesProcessor(@NotNull PsiElement place, PsiFile placeFile) { |
| super(new PsiConflictResolver[]{DuplicateConflictResolver.INSTANCE}, new SmartList<CandidateInfo>(), place, placeFile); |
| } |
| |
| @Override |
| public void add(@NotNull PsiElement element, @NotNull PsiSubstitutor substitutor) { |
| if (element instanceof PsiMethod) { |
| final PsiMethod method = (PsiMethod)element; |
| addMethod(method, substitutor, isInStaticScope() && !method.hasModifierProperty(PsiModifier.STATIC)); |
| } |
| } |
| |
| public void addMethod(@NotNull PsiMethod method, final PsiSubstitutor substitutor, final boolean staticProblem) { |
| final boolean isAccessible = JavaResolveUtil.isAccessible(method, getContainingClass(method), method.getModifierList(), |
| myPlace, myAccessClass, myCurrentFileContext, myPlaceFile) && |
| !isShadowed(method); |
| if (isAccepted(method)) { |
| add(createCandidateInfo(method, substitutor, staticProblem, isAccessible, false)); |
| if (acceptVarargs() && method.isVarArgs() && PsiUtil.isLanguageLevel8OrHigher(myPlace)) { |
| add(createCandidateInfo(method, substitutor, staticProblem, isAccessible, true)); |
| } |
| myHasAccessibleStaticCorrectCandidate |= isAccessible && !staticProblem; |
| } |
| } |
| |
| protected PsiClass getContainingClass(PsiMethod method) { |
| return method.getContainingClass(); |
| } |
| |
| protected boolean acceptVarargs() { |
| return false; |
| } |
| |
| protected MethodCandidateInfo createCandidateInfo(@NotNull PsiMethod method, @NotNull PsiSubstitutor substitutor, |
| final boolean staticProblem, final boolean accessible, final boolean varargs) { |
| final PsiExpressionList argumentList = getArgumentList(); |
| return new MethodCandidateInfo(method, substitutor, !accessible, staticProblem, argumentList, myCurrentFileContext, |
| null, getTypeArguments(), getLanguageLevel()) { |
| |
| private PsiType[] myExpressionTypes; |
| |
| @Override |
| public PsiType[] getArgumentTypes() { |
| if (myExpressionTypes == null && argumentList != null) { |
| final PsiType[] expressionTypes = getExpressionTypes(argumentList); |
| if (MethodCandidateInfo.isOverloadCheck()) { |
| return expressionTypes; |
| } |
| myExpressionTypes = expressionTypes; |
| } |
| return myExpressionTypes; |
| } |
| |
| @Override |
| public boolean isVarargs() { |
| return varargs; |
| } |
| }; |
| } |
| |
| protected static PsiType[] getExpressionTypes(PsiExpressionList argumentList) { |
| return argumentList != null ? argumentList.getExpressionTypes() : null; |
| } |
| |
| protected boolean isAccepted(final PsiMethod candidate) { |
| if (!isConstructor()) { |
| return !candidate.isConstructor() && candidate.getName().equals(getName(ResolveState.initial())); |
| } |
| else { |
| if (!candidate.isConstructor()) return false; |
| if (myAccessClass == null) return true; |
| if (myAccessClass instanceof PsiAnonymousClass) { |
| final PsiClass containingClass = getContainingClass(candidate); |
| return containingClass != null && containingClass.equals(myAccessClass.getSuperClass()); |
| } |
| return myAccessClass.isEquivalentTo(getContainingClass(candidate)); |
| } |
| } |
| |
| protected boolean isShadowed(final PsiMethod candidate) { |
| if (myCurrentFileContext instanceof PsiImportStaticStatement) { |
| for (JavaResolveResult result : getResults()) { |
| if (result.getElement() != candidate && |
| result.isAccessible() && |
| !(result.getCurrentFileResolveScope() instanceof PsiImportStaticStatement)) return true; |
| } |
| } |
| return false; |
| } |
| |
| public CandidateInfo[] getCandidates() { |
| final JavaResolveResult[] resolveResult = getResult(); |
| if (resolveResult.length == 0) return CandidateInfo.EMPTY_ARRAY; |
| final CandidateInfo[] infos = new CandidateInfo[resolveResult.length]; |
| //noinspection SuspiciousSystemArraycopy |
| System.arraycopy(resolveResult, 0, infos, 0, resolveResult.length); |
| return infos; |
| } |
| } |