From 774e6e23e9d9a840cbb6255b6e2e2810a06ddbdb Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Fri, 24 Jan 2014 19:32:19 +0400 Subject: [PATCH] Support "Find usages" for declarations contained in the library #KT-4452 Fixed --- .../KotlinFindUsagesHandlerFactory.kt | 23 +++- .../refactoring/JetRefactoringUtil.java | 122 ++++++------------ 2 files changed, 56 insertions(+), 89 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/findUsages/KotlinFindUsagesHandlerFactory.kt b/idea/src/org/jetbrains/jet/plugin/findUsages/KotlinFindUsagesHandlerFactory.kt index c87fd1abfdd..94f776a6844 100644 --- a/idea/src/org/jetbrains/jet/plugin/findUsages/KotlinFindUsagesHandlerFactory.kt +++ b/idea/src/org/jetbrains/jet/plugin/findUsages/KotlinFindUsagesHandlerFactory.kt @@ -31,8 +31,13 @@ import org.jetbrains.jet.plugin.findUsages.handlers.KotlinTypeParameterFindUsage import org.jetbrains.jet.lang.psi.JetParameter import org.jetbrains.jet.lang.psi.JetNamedDeclaration import org.jetbrains.jet.lang.psi.JetClassOrObject +import com.intellij.find.findUsages.FindUsagesManager +import com.intellij.find.findUsages.JavaFindUsagesHandlerFactory +import com.intellij.psi.PsiMethod public class KotlinFindUsagesHandlerFactory(project: Project) : FindUsagesHandlerFactory() { + val javaHandlerFactory = JavaFindUsagesHandlerFactory(project) + val findFunctionOptions = KotlinFunctionFindUsagesOptions(project) val findPropertyOptions = KotlinPropertyFindUsagesOptions(project) val findClassOptions = KotlinClassFindUsagesOptions(project) @@ -45,7 +50,7 @@ public class KotlinFindUsagesHandlerFactory(project: Project) : FindUsagesHandle element is JetParameter || element is JetTypeParameter - public override fun createFindUsagesHandler(element: PsiElement, forHighlightUsages: Boolean): FindUsagesHandler { + public override fun createFindUsagesHandler(element: PsiElement, forHighlightUsages: Boolean): FindUsagesHandler? { when(element) { is JetClassOrObject -> return KotlinFindClassUsagesHandler(element, this) @@ -56,13 +61,21 @@ public class KotlinFindUsagesHandlerFactory(project: Project) : FindUsagesHandle return if (forHighlightUsages) KotlinFindMemberUsagesHandler.getInstance(declaration, this) else JetRefactoringUtil.checkSuperMethods(declaration, null, "super.methods.action.key.find.usages")?.let { callables -> when (callables.size()) { - 0 -> null - 1 -> - KotlinFindMemberUsagesHandler.getInstance(callables.get(0) as JetNamedDeclaration, this) + 0 -> FindUsagesHandler.NULL_HANDLER + 1 -> { + val callable = callables.get(0) + when (callable) { + is JetNamedDeclaration -> + KotlinFindMemberUsagesHandler.getInstance(callable, this) + is PsiMethod -> + javaHandlerFactory.createFindUsagesHandler(callable, forHighlightUsages) + else -> null + } + } else -> KotlinFindMemberUsagesHandler.getInstance(declaration, callables, this) } - } ?: FindUsagesHandler.NULL_HANDLER + } } is JetTypeParameter -> diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringUtil.java b/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringUtil.java index a0e1a1d4a5a..7299fceb301 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringUtil.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringUtil.java @@ -19,13 +19,14 @@ package org.jetbrains.jet.plugin.refactoring; import com.intellij.codeInsight.unwrap.ScopeHighlighter; import com.intellij.ide.IdeBundle; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.popup.JBPopupAdapter; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.LightweightWindowEvent; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; -import com.intellij.psi.search.searches.DeepestSuperMethodsSearch; import com.intellij.psi.util.PsiFormatUtil; import com.intellij.psi.util.PsiFormatUtilBase; import com.intellij.ui.components.JBList; @@ -33,12 +34,12 @@ import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.asJava.LightClassUtil; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.impl.LocalVariableDescriptor; 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.OverridingUtil; import org.jetbrains.jet.lang.resolve.java.jetAsJava.KotlinLightMethod; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.PackageType; @@ -48,6 +49,7 @@ import org.jetbrains.jet.lexer.JetKeywordToken; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.plugin.JetBundle; import org.jetbrains.jet.plugin.codeInsight.CodeInsightUtils; +import org.jetbrains.jet.plugin.codeInsight.DescriptorToDeclarationUtil; import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; import org.jetbrains.jet.renderer.DescriptorRenderer; @@ -111,89 +113,48 @@ public class JetRefactoringUtil { return markAsJava ? "[Java] " + description : description; } - private static PsiElement toJetDeclarationOrMethod(PsiMethod method) { - return (method instanceof KotlinLightMethod) ? ((KotlinLightMethod) method).getOrigin() : method; - } - - @NotNull - private static List getFunctionSuperDeclarations(@NotNull JetNamedFunction function) { - PsiMethod lightMethod = LightClassUtil.getLightClassMethod(function); - if (lightMethod == null) return Collections.emptyList(); - - return ContainerUtil.map( - DeepestSuperMethodsSearch.search(lightMethod).findAll(), - new Function() { - @Override - public PsiElement fun(PsiMethod method) { - return toJetDeclarationOrMethod(method); - } - } - ); - } - - @NotNull - private static List getPropertySuperDeclarations(@NotNull JetDeclaration declaration) { - LightClassUtil.PropertyAccessorsPsiMethods lightMethods; - if (declaration instanceof JetProperty) { - lightMethods = LightClassUtil.getLightClassPropertyMethods((JetProperty) declaration); - } - else if (declaration instanceof JetParameter) { - lightMethods = LightClassUtil.getLightClassPropertyMethods((JetParameter) declaration); - } - else return Collections.emptyList(); - - Collection foundMethods = new HashSet(); - if (lightMethods.getGetter() != null) { - foundMethods.addAll(DeepestSuperMethodsSearch.search(lightMethods.getGetter()).findAll()); - } - if (lightMethods.getSetter() != null) { - foundMethods.addAll(DeepestSuperMethodsSearch.search(lightMethods.getSetter()).findAll()); - } - - Set declarations = new HashSet(); - for (PsiMethod method : foundMethods) { - declarations.add(toJetDeclarationOrMethod(method)); - } - - return new ArrayList(declarations); - } - - @NotNull - private static List getSuperDeclarations(@NotNull JetDeclaration declaration) { - if (declaration instanceof JetNamedFunction) return getFunctionSuperDeclarations((JetNamedFunction) declaration); - if (declaration instanceof JetProperty || declaration instanceof JetParameter) return getPropertySuperDeclarations(declaration); - return Collections.emptyList(); - } - @Nullable public static List checkSuperMethods( @NotNull JetDeclaration declaration, @Nullable Collection ignore, @NotNull String actionStringKey ) { - BindingContext bindingContext = - AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) declaration.getContainingFile()).getBindingContext(); + final BindingContext bindingContext = AnalyzerFacadeWithCache.getContextForElement(declaration); - DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration); + CallableDescriptor declarationDescriptor = + (CallableDescriptor)bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration); - if (declarationDescriptor instanceof LocalVariableDescriptor) { + if (declarationDescriptor == null || declarationDescriptor instanceof LocalVariableDescriptor) { return Collections.singletonList(declaration); } - List superDeclarations = getSuperDeclarations(declaration); + final Project project = declaration.getProject(); + Map overriddenElementsToDescriptor = ContainerUtil.map2Map( + OverridingUtil.getAllOverriddenDescriptors(declarationDescriptor), + new Function>() { + @Override + public Pair fun(CallableDescriptor descriptor) { + return new Pair( + DescriptorToDeclarationUtil.getDeclaration(project, descriptor, bindingContext), + descriptor + ); + } + } + ); + overriddenElementsToDescriptor.remove(null); if (ignore != null) { - superDeclarations.removeAll(ignore); + overriddenElementsToDescriptor.keySet().removeAll(ignore); } - if (superDeclarations.isEmpty()) return Collections.singletonList(declaration); + if (overriddenElementsToDescriptor.isEmpty()) return Collections.singletonList(declaration); - java.util.List superClasses = getClassDescriptions(bindingContext, superDeclarations); - return askUserForMethodsToSearch(declaration, declarationDescriptor, superDeclarations, superClasses, actionStringKey); + List superClasses = getClassDescriptions(overriddenElementsToDescriptor); + return askUserForMethodsToSearch(declaration, declarationDescriptor, overriddenElementsToDescriptor, superClasses, actionStringKey); } @NotNull private static List askUserForMethodsToSearch( @NotNull JetDeclaration declaration, - @NotNull DeclarationDescriptor declarationDescriptor, - @NotNull List superMethods, + @NotNull CallableDescriptor declarationDescriptor, + @NotNull Map overriddenElementsToDescriptor, @NotNull List superClasses, @NotNull String actionStringKey ) { @@ -211,7 +172,7 @@ public class JetRefactoringUtil { ); switch (exitCode) { case Messages.YES: - return superMethods; + return ContainerUtil.newArrayList(overriddenElementsToDescriptor.keySet()); case Messages.NO: return Collections.singletonList(declaration); default: @@ -220,31 +181,24 @@ public class JetRefactoringUtil { } @NotNull - private static List getClassDescriptions( - @NotNull final BindingContext bindingContext, @NotNull Collection superMethods - ) { + private static List getClassDescriptions(@NotNull Map overriddenElementsToDescriptor) { return ContainerUtil.map( - superMethods, - new Function() { + overriddenElementsToDescriptor.entrySet(), + new Function, String>() { @Override - public String fun(PsiElement element) { + public String fun(Map.Entry entry) { String description; + PsiElement element = entry.getKey(); + CallableDescriptor descriptor = entry.getValue(); if (element instanceof JetNamedFunction || element instanceof JetProperty) { - DeclarationDescriptor descriptor = - bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element); - assert descriptor != null; - - DeclarationDescriptor containingDescriptor = descriptor.getContainingDeclaration(); - assert containingDescriptor != null; - - description = formatClassDescriptor(containingDescriptor); + description = formatClassDescriptor(descriptor.getContainingDeclaration()); } else { - assert element instanceof PsiMethod; + assert element instanceof PsiMethod : "Invalid element: " + element.getText(); PsiClass psiClass = ((PsiMethod) element).getContainingClass(); - assert psiClass != null; + assert psiClass != null : "Invalid element: " + element.getText(); description = formatPsiClass(psiClass, true, false); }