Unified resolve and multiResolve for references.
This commit is contained in:
@@ -83,17 +83,6 @@ public class BindingContextUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<PsiElement> resolveToDeclarationPsiElements(@NotNull BindingContext bindingContext, @Nullable JetReferenceExpression referenceExpression) {
|
||||
DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, referenceExpression);
|
||||
if (declarationDescriptor == null) {
|
||||
return Lists.newArrayList(bindingContext.get(BindingContext.LABEL_TARGET, referenceExpression));
|
||||
}
|
||||
|
||||
return descriptorToDeclarations(bindingContext, declarationDescriptor);
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
public static VariableDescriptor extractVariableDescriptorIfAny(@NotNull BindingContext bindingContext, @Nullable JetElement element, boolean onlyReference) {
|
||||
DeclarationDescriptor descriptor = null;
|
||||
|
||||
@@ -16,28 +16,30 @@
|
||||
|
||||
package org.jetbrains.jet.plugin.references;
|
||||
|
||||
import com.beust.jcommander.internal.Lists;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.MultiRangeReference;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetArrayAccessExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetContainerNode;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.INDEXED_LVALUE_GET;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.INDEXED_LVALUE_SET;
|
||||
|
||||
class JetArrayAccessReference extends JetPsiReference implements MultiRangeReference {
|
||||
private JetArrayAccessExpression expression;
|
||||
private final JetArrayAccessExpression expression;
|
||||
|
||||
public static PsiReference[] create(JetArrayAccessExpression expression) {
|
||||
JetContainerNode indicesNode = expression.getIndicesNode();
|
||||
@@ -54,32 +56,22 @@ class JetArrayAccessReference extends JetPsiReference implements MultiRangeRefer
|
||||
return getElement().getTextRange().shiftRight(-getElement().getTextOffset());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected PsiElement doResolve() {
|
||||
BindingContext bindingContext = AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) getElement().getContainingFile())
|
||||
.getBindingContext();
|
||||
ResolvedCall<FunctionDescriptor> getFunction = bindingContext.get(INDEXED_LVALUE_GET, expression);
|
||||
ResolvedCall<FunctionDescriptor> setFunction = bindingContext.get(INDEXED_LVALUE_SET, expression);
|
||||
if (getFunction != null && setFunction != null) {
|
||||
return null; // Call doMultiResolve
|
||||
}
|
||||
return super.doResolve();
|
||||
}
|
||||
protected Collection<? extends DeclarationDescriptor> getTargetDescriptors(@NotNull BindingContext context) {
|
||||
List<DeclarationDescriptor> result = Lists.newArrayList();
|
||||
|
||||
@Override
|
||||
protected ResolveResult[] doMultiResolve() {
|
||||
BindingContext bindingContext = AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) getElement().getContainingFile())
|
||||
.getBindingContext();
|
||||
ResolvedCall<FunctionDescriptor> getFunction = bindingContext.get(INDEXED_LVALUE_GET, expression);
|
||||
ResolvedCall<FunctionDescriptor> setFunction = bindingContext.get(INDEXED_LVALUE_SET, expression);
|
||||
if (getFunction == null || setFunction == null) {
|
||||
return new ResolveResult[0];
|
||||
ResolvedCall<FunctionDescriptor> getFunction = context.get(INDEXED_LVALUE_GET, expression);
|
||||
if (getFunction != null) {
|
||||
result.add(getFunction.getResultingDescriptor());
|
||||
}
|
||||
PsiElement getFunctionElement = BindingContextUtils.callableDescriptorToDeclaration(bindingContext, getFunction.getResultingDescriptor());
|
||||
assert getFunctionElement != null;
|
||||
PsiElement setFunctionElement = BindingContextUtils.callableDescriptorToDeclaration(bindingContext, setFunction.getResultingDescriptor());
|
||||
assert setFunctionElement != null;
|
||||
return new ResolveResult[] {new PsiElementResolveResult(getFunctionElement, true), new PsiElementResolveResult(setFunctionElement, true)};
|
||||
|
||||
ResolvedCall<FunctionDescriptor> setFunction = context.get(INDEXED_LVALUE_SET, expression);
|
||||
if (setFunction != null) {
|
||||
result.add(setFunction.getResultingDescriptor());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -18,19 +18,21 @@ package org.jetbrains.jet.plugin.references;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.MultiRangeReference;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLVED_CALL;
|
||||
@@ -50,31 +52,18 @@ class JetInvokeFunctionReference extends JetPsiReference implements MultiRangeRe
|
||||
return getElement().getTextRange().shiftRight(-getElement().getTextOffset());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected PsiElement doResolve() {
|
||||
protected Collection<? extends DeclarationDescriptor> getTargetDescriptors(@NotNull BindingContext context) {
|
||||
JetExpression calleeExpression = ((JetCallExpression) myExpression).getCalleeExpression();
|
||||
BindingContext bindingContext = AnalyzerFacadeWithCache.getContextForElement(myExpression);
|
||||
ResolvedCall<? extends CallableDescriptor> resolvedCall = context.get(RESOLVED_CALL, calleeExpression);
|
||||
|
||||
ResolvedCall<? extends CallableDescriptor> invokeFunction = bindingContext.get(RESOLVED_CALL, calleeExpression);
|
||||
|
||||
if (invokeFunction != null && invokeFunction instanceof VariableAsFunctionResolvedCall) {
|
||||
FunctionDescriptor resultingDescriptor = ((VariableAsFunctionResolvedCall) invokeFunction).getResultingDescriptor();
|
||||
return BindingContextUtils.callableDescriptorToDeclaration(bindingContext, resultingDescriptor);
|
||||
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
|
||||
return Collections.singleton(((VariableAsFunctionResolvedCall) resolvedCall).getResultingDescriptor());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResolveResult[] doMultiResolve() {
|
||||
// TODO If there are more than one invoke(), add all function ("ambiguity"). See JetPsiReference
|
||||
PsiElement element = doResolve();
|
||||
if (element == null) {
|
||||
return ResolveResult.EMPTY_ARRAY;
|
||||
}
|
||||
return new ResolveResult[] {new PsiElementResolveResult(element, true)};
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TextRange> getRanges() {
|
||||
JetCallExpression callExpression = (JetCallExpression) myExpression;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.jet.plugin.references;
|
||||
|
||||
import com.beust.jcommander.internal.Sets;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiElementResolveResult;
|
||||
@@ -25,19 +26,16 @@ import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.java.jetAsJava.KotlinLightMethod;
|
||||
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.AMBIGUOUS_LABEL_TARGET;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.AMBIGUOUS_REFERENCE_TARGET;
|
||||
import static org.jetbrains.jet.plugin.codeInsight.DescriptorToDeclarationUtil.findDeclarationsForDescriptorWithoutTrace;
|
||||
|
||||
public abstract class JetPsiReference implements PsiPolyVariantReference {
|
||||
@@ -60,12 +58,16 @@ public abstract class JetPsiReference implements PsiPolyVariantReference {
|
||||
@NotNull
|
||||
@Override
|
||||
public ResolveResult[] multiResolve(boolean incompleteCode) {
|
||||
return doMultiResolve();
|
||||
return PsiElementResolveResult.createResults(resolveToPsiElements());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement resolve() {
|
||||
return doResolve();
|
||||
Collection<? extends PsiElement> psiElements = resolveToPsiElements();
|
||||
if (psiElements.size() == 1) {
|
||||
return psiElements.iterator().next();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -103,59 +105,50 @@ public abstract class JetPsiReference implements PsiPolyVariantReference {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected PsiElement doResolve() {
|
||||
@NotNull
|
||||
private Collection<? extends PsiElement> resolveToPsiElements() {
|
||||
BindingContext context = AnalyzerFacadeWithCache.getContextForElement(myExpression);
|
||||
List<PsiElement> psiElements = BindingContextUtils.resolveToDeclarationPsiElements(context, myExpression);
|
||||
if (psiElements.size() == 1) {
|
||||
return psiElements.iterator().next();
|
||||
}
|
||||
if (psiElements.size() > 1) {
|
||||
return null;
|
||||
}
|
||||
DeclarationDescriptor referencedDescriptor = context.get(BindingContext.REFERENCE_TARGET, myExpression);
|
||||
if (referencedDescriptor == null) {
|
||||
return null;
|
||||
}
|
||||
Collection<PsiElement> elements = findDeclarationsForDescriptorWithoutTrace(myExpression.getProject(), referencedDescriptor);
|
||||
if (elements.size() == 1) {
|
||||
return elements.iterator().next();
|
||||
}
|
||||
return null;
|
||||
|
||||
return resolveToPsiElements(context);
|
||||
}
|
||||
|
||||
protected ResolveResult[] doMultiResolve() {
|
||||
JetFile file = (JetFile) getElement().getContainingFile();
|
||||
BindingContext bindingContext = AnalyzerFacadeWithCache.analyzeFileWithCache(file).getBindingContext();
|
||||
Collection<? extends DeclarationDescriptor> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression);
|
||||
if (declarationDescriptors == null) {
|
||||
List<PsiElement> psiElements = BindingContextUtils.resolveToDeclarationPsiElements(bindingContext, myExpression);
|
||||
if (psiElements.size() > 1) {
|
||||
return PsiElementResolveResult.createResults(psiElements);
|
||||
@NotNull
|
||||
private Collection<? extends PsiElement> resolveToPsiElements(@NotNull BindingContext context) {
|
||||
Collection<? extends DeclarationDescriptor> targetDescriptors = getTargetDescriptors(context);
|
||||
|
||||
if (targetDescriptors != null) {
|
||||
assert !(targetDescriptors.isEmpty()) : "targetDescriptors is not null, but empty, for " + myExpression.getText();
|
||||
Set<PsiElement> result = Sets.newHashSet();
|
||||
for (DeclarationDescriptor target : targetDescriptors) {
|
||||
result.addAll(BindingContextUtils.descriptorToDeclarations(context, target));
|
||||
result.addAll(findDeclarationsForDescriptorWithoutTrace(myExpression.getProject(), target));
|
||||
}
|
||||
Collection<? extends PsiElement> labelTargets = bindingContext.get(AMBIGUOUS_LABEL_TARGET, myExpression);
|
||||
if (labelTargets != null && !labelTargets.isEmpty()) {
|
||||
return PsiElementResolveResult.createResults(labelTargets);
|
||||
}
|
||||
Collection<PsiElement> standardLibraryElements = resolveStandardLibrarySymbol(bindingContext);
|
||||
if (standardLibraryElements.size() > 1) {
|
||||
return PsiElementResolveResult.createResults(standardLibraryElements);
|
||||
}
|
||||
return ResolveResult.EMPTY_ARRAY;
|
||||
return result;
|
||||
}
|
||||
|
||||
List<ResolveResult> results = new ArrayList<ResolveResult>(declarationDescriptors.size());
|
||||
for (DeclarationDescriptor descriptor : declarationDescriptors) {
|
||||
List<PsiElement> elements = BindingContextUtils.descriptorToDeclarations(bindingContext, descriptor);
|
||||
for (PsiElement element : elements) {
|
||||
results.add(new PsiElementResolveResult(element, true));
|
||||
}
|
||||
Collection<? extends PsiElement> labelTargets = getLabelTargets(context);
|
||||
if (labelTargets != null) {
|
||||
return labelTargets;
|
||||
}
|
||||
return results.toArray(new ResolveResult[results.size()]);
|
||||
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
private Collection<PsiElement> resolveStandardLibrarySymbol(@NotNull BindingContext bindingContext) {
|
||||
return myExpression.getProject().getComponent(BuiltInsReferenceResolver.class)
|
||||
.resolveBuiltInSymbol(bindingContext, myExpression);
|
||||
@Nullable
|
||||
protected Collection<? extends DeclarationDescriptor> getTargetDescriptors(@NotNull BindingContext context) {
|
||||
DeclarationDescriptor targetDescriptor = context.get(BindingContext.REFERENCE_TARGET, myExpression);
|
||||
if (targetDescriptor != null) {
|
||||
return Collections.singleton(targetDescriptor);
|
||||
}
|
||||
return context.get(BindingContext.AMBIGUOUS_REFERENCE_TARGET, myExpression);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Collection<? extends PsiElement> getLabelTargets(@NotNull BindingContext context) {
|
||||
PsiElement labelTarget = context.get(BindingContext.LABEL_TARGET, myExpression);
|
||||
if (labelTarget != null) {
|
||||
return Collections.singleton(labelTarget);
|
||||
}
|
||||
return context.get(BindingContext.AMBIGUOUS_LABEL_TARGET, myExpression);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ public class BuiltInsReferenceResolverTest extends ResolveTestCase {
|
||||
JetPsiReference reference = (JetPsiReference) configureByFile(getTestName(true) + ".kt");
|
||||
PsiElement resolved = reference.resolve();
|
||||
assertNotNull(resolved);
|
||||
assertEmpty(reference.multiResolve(false));
|
||||
assertEquals(1, reference.multiResolve(false).length);
|
||||
|
||||
List<PsiComment> comments = PsiTreeUtil.getChildrenOfTypeAsList(getFile(), PsiComment.class);
|
||||
String[] expectedTarget = comments.get(comments.size() - 1).getText().substring(2).split(":");
|
||||
|
||||
Reference in New Issue
Block a user