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;
}
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);
}
}
}
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;
}
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;
}
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);
}
Aggregations