blob: c12972d354c79313293d13d43b202c19b2565651 [file] [log] [blame]
/*
* 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;
}
}