From b8d2e62d2c404ce15cb134538f3f7cd5526ca140 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Mon, 16 Apr 2012 18:57:41 +0400 Subject: [PATCH] sometimes descriptor has more than one declaration --- .../jet/lang/resolve/BindingContextUtils.java | 52 +++++++++++++++++++ .../plugin/references/JetPsiReference.java | 22 +++++--- 2 files changed, 67 insertions(+), 7 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java index f81bbde54f5..e33be6780f7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java @@ -16,6 +16,7 @@ package org.jetbrains.jet.lang.resolve; +import com.google.common.collect.Lists; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,6 +32,8 @@ import org.jetbrains.jet.lang.types.lang.JetStandardClasses; import org.jetbrains.jet.util.slicedmap.ReadOnlySlice; import org.jetbrains.jet.util.slicedmap.Slices; +import java.util.ArrayList; +import java.util.List; import java.util.Set; /** @@ -83,6 +86,27 @@ public class BindingContextUtils { return null; } + @NotNull + public static List 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)); + } + + List elements = descriptorToDeclarations(bindingContext, declarationDescriptor); + if (elements.size() > 0) { + return elements; + } + + // TODO: Need to have a valid stubs for standard classes + if (referenceExpression != null && JetStandardClasses.getAllStandardClasses().contains(declarationDescriptor)) { + return Lists.newArrayList(referenceExpression.getContainingFile()); + } + + return Lists.newArrayList(); + } + + @Nullable public static VariableDescriptor extractVariableDescriptorIfAny(@NotNull BindingContext bindingContext, @Nullable JetElement element, boolean onlyReference) { DeclarationDescriptor descriptor = null; @@ -131,6 +155,21 @@ public class BindingContextUtils { } } + @NotNull + public static List descriptorToDeclarations(@NotNull BindingContext context, @NotNull DeclarationDescriptor descriptor) { + if (descriptor instanceof CallableMemberDescriptor) { + return callableDescriptorToDeclarations(context, (CallableMemberDescriptor) descriptor); + } + else { + PsiElement psiElement = descriptorToDeclaration(context, descriptor); + if (psiElement != null) { + return Lists.newArrayList(psiElement); + } else { + return Lists.newArrayList(); + } + } + } + @Nullable public static PsiElement callableDescriptorToDeclaration(@NotNull BindingContext context, @NotNull CallableMemberDescriptor callable) { if (callable.getKind() != CallableMemberDescriptor.Kind.DECLARATION) { @@ -148,6 +187,19 @@ public class BindingContextUtils { return doGetDescriptorToDeclaration(context, callable.getOriginal()); } + private static List callableDescriptorToDeclarations(@NotNull BindingContext context, @NotNull CallableMemberDescriptor callable) { + if (callable.getKind() != CallableMemberDescriptor.Kind.DECLARATION) { + List r = new ArrayList(); + Set overridenDescriptors = callable.getOverriddenDescriptors(); + for (CallableMemberDescriptor overriden : overridenDescriptors) { + r.addAll(callableDescriptorToDeclarations(context, overriden)); + } + return r; + } + PsiElement psiElement = doGetDescriptorToDeclaration(context, callable); + return psiElement != null ? Lists.newArrayList(psiElement) : Lists.newArrayList(); + } + @Nullable public static PsiElement classDescriptorToDeclaration(@NotNull BindingContext context, @NotNull ClassDescriptor clazz) { return doGetDescriptorToDeclaration(context, clazz); diff --git a/idea/src/org/jetbrains/jet/plugin/references/JetPsiReference.java b/idea/src/org/jetbrains/jet/plugin/references/JetPsiReference.java index 3c6351df90d..cb64f9cd50c 100644 --- a/idea/src/org/jetbrains/jet/plugin/references/JetPsiReference.java +++ b/idea/src/org/jetbrains/jet/plugin/references/JetPsiReference.java @@ -33,6 +33,7 @@ import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade; import java.util.ArrayList; import java.util.Collection; +import java.util.List; import static org.jetbrains.jet.lang.resolve.BindingContext.AMBIGUOUS_REFERENCE_TARGET; @@ -102,9 +103,12 @@ public abstract class JetPsiReference implements PsiPolyVariantReference { protected PsiElement doResolve() { JetFile file = (JetFile) getElement().getContainingFile(); BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file).getBindingContext(); - PsiElement psiElement = BindingContextUtils.resolveToDeclarationPsiElement(bindingContext, myExpression); - if (psiElement != null) { - return psiElement; + List psiElement = BindingContextUtils.resolveToDeclarationPsiElements(bindingContext, myExpression); + if (psiElement.size() == 1) { + return psiElement.iterator().next(); + } + if (psiElement.size() > 1) { + return null; } Collection declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression); if (declarationDescriptors != null) return null; @@ -123,13 +127,17 @@ public abstract class JetPsiReference implements PsiPolyVariantReference { ArrayList results = new ArrayList(declarationDescriptors.size()); for (DeclarationDescriptor descriptor : declarationDescriptors) { - PsiElement element = BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor); - if (element == null) { + List elements = BindingContextUtils.descriptorToDeclarations(bindingContext, descriptor); + if (elements.isEmpty()) { // TODO: Need a better resolution for Intrinsic function (KT-975) - element = file; + results.add(new PsiElementResolveResult(file, true)); + } + else { + for (PsiElement element : elements) { + results.add(new PsiElementResolveResult(element, true)); + } } - results.add(new PsiElementResolveResult(element, true)); } return results.toArray(new ResolveResult[results.size()]);