From eb1d458807d4e55fe48847ba1b4107c0a1026970 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Fri, 2 Aug 2013 16:12:18 +0400 Subject: [PATCH] Move checkSuperMethods and format methods to RefactoringUtil --- .../refactoring/JetRefactoringUtil.java | 210 +++++++++++++++++- .../safeDelete/KotlinOverridingDialog.java | 3 +- .../safeDelete/KotlinSafeDeleteProcessor.java | 208 +---------------- 3 files changed, 215 insertions(+), 206 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringUtil.java b/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringUtil.java index c08c7aa94d1..7ca7ab1f5bf 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringUtil.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringUtil.java @@ -17,34 +17,46 @@ 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.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.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiWhiteSpace; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.*; +import com.intellij.psi.util.PsiFormatUtil; +import com.intellij.psi.util.PsiFormatUtilBase; import com.intellij.ui.components.JBList; +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.lang.descriptors.CallableMemberDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.Visibilities; import org.jetbrains.jet.lang.descriptors.Visibility; 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.java.JetClsMethod; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.NamespaceType; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 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.project.AnalyzerFacadeWithCache; +import org.jetbrains.jet.renderer.DescriptorRenderer; import javax.swing.*; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.*; -import java.util.ArrayList; +import java.util.*; +import java.util.List; /** * User: Alefas @@ -72,6 +84,196 @@ public class JetRefactoringUtil { throw new IllegalArgumentException("Unexpected visibility '" + visibility + "'"); } + @NotNull + public static String wrapOrSkip(@NotNull String s, boolean inCode) { + return inCode ? "" + s + "" : s; + } + + @NotNull + public static String formatClassDescriptor(@NotNull DeclarationDescriptor classDescriptor) { + return DescriptorRenderer.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(classDescriptor); + } + + @NotNull + public static String formatPsiClass( + @NotNull PsiClass psiClass, + boolean markAsJava, + boolean inCode + ) { + String description; + + String kind = psiClass.isInterface() ? "interface " : "class "; + description = kind + PsiFormatUtil.formatClass( + psiClass, + PsiFormatUtilBase.SHOW_CONTAINING_CLASS + | PsiFormatUtilBase.SHOW_NAME + | PsiFormatUtilBase.SHOW_PARAMETERS + | PsiFormatUtilBase.SHOW_TYPE + ); + description = wrapOrSkip(description, inCode); + + return markAsJava ? "[Java] " + description : description; + } + + @Nullable + public static Collection checkSuperMethods( + @NotNull JetDeclaration declaration, @Nullable Collection ignore + ) { + final BindingContext bindingContext = + AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) declaration.getContainingFile()).getBindingContext(); + + DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration); + if (!(declarationDescriptor instanceof CallableMemberDescriptor)) return null; + + CallableMemberDescriptor callableDescriptor = (CallableMemberDescriptor) declarationDescriptor; + Set overridenDescriptors = callableDescriptor.getOverriddenDescriptors(); + + Collection superMethods = ContainerUtil.map( + overridenDescriptors, + new Function() { + @Override + public PsiElement fun(CallableMemberDescriptor descriptor) { + return BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor); + } + } + ); + if (ignore != null) { + superMethods.removeAll(ignore); + } + + if (superMethods.isEmpty()) return Collections.singletonList(declaration); + + java.util.List superClasses = getClassDescriptions(bindingContext, superMethods); + return askUserForMethodsToSearch(declaration, callableDescriptor, superMethods, superClasses); + } + + @NotNull + private static Collection askUserForMethodsToSearch( + @NotNull JetDeclaration declaration, + @NotNull CallableMemberDescriptor callableDescriptor, + @NotNull Collection superMethods, + @NotNull List superClasses + ) { + String superClassesStr = "\n" + StringUtil.join(superClasses, ""); + String message = JetBundle.message( + "x.overrides.y.in.class.list", + DescriptorRenderer.COMPACT.render(callableDescriptor), + DescriptorRenderer.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(callableDescriptor.getContainingDeclaration()), + superClassesStr + ); + + int exitCode = Messages.showYesNoCancelDialog( + declaration.getProject(), message, IdeBundle.message("title.warning"), Messages.getQuestionIcon() + ); + switch (exitCode) { + case Messages.YES: + return superMethods; + case Messages.NO: + return Collections.singletonList(declaration); + default: + return Collections.emptyList(); + } + } + + @NotNull + private static List getClassDescriptions( + @NotNull final BindingContext bindingContext, @NotNull Collection superMethods + ) { + return ContainerUtil.map( + superMethods, + new Function() { + @Override + public String fun(PsiElement element) { + String description; + + 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); + } + else { + assert element instanceof PsiMethod; + + PsiClass psiClass = ((PsiMethod) element).getContainingClass(); + assert psiClass != null; + + description = formatPsiClass(psiClass, true, false); + } + + return " " + description + "\n"; + } + } + ); + } + + @NotNull + public static String formatClass( + @NotNull DeclarationDescriptor classDescriptor, + @NotNull BindingContext bindingContext, + boolean inCode + ) { + PsiElement element = BindingContextUtils.descriptorToDeclaration(bindingContext, classDescriptor); + if (element instanceof PsiClass) { + return formatPsiClass((PsiClass) element, false, inCode); + } + + return wrapOrSkip(formatClassDescriptor(classDescriptor), inCode); + } + + @NotNull + public static String formatFunction( + @NotNull DeclarationDescriptor functionDescriptor, + @NotNull BindingContext bindingContext, + boolean inCode + ) { + PsiElement element = BindingContextUtils.descriptorToDeclaration(bindingContext, functionDescriptor); + if (element instanceof PsiMethod) { + return formatPsiMethod((PsiMethod) element, false, inCode); + } + + return wrapOrSkip(formatFunctionDescriptor(functionDescriptor), inCode); + } + + @NotNull + private static String formatFunctionDescriptor(@NotNull DeclarationDescriptor functionDescriptor) { + return DescriptorRenderer.COMPACT.render(functionDescriptor); + } + + @NotNull + public static String formatPsiMethod( + @NotNull PsiMethod psiMethod, + boolean showContainingClass, + boolean inCode) { + int options = PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS | PsiFormatUtilBase.SHOW_TYPE; + if (showContainingClass) { + //noinspection ConstantConditions + options |= PsiFormatUtilBase.SHOW_CONTAINING_CLASS; + } + + String description = PsiFormatUtil.formatMethod(psiMethod, PsiSubstitutor.EMPTY, options, PsiFormatUtilBase.SHOW_TYPE); + description = wrapOrSkip(description, inCode); + + return "[Java] " + description; + } + + @NotNull + public static String formatJavaOrLightMethod(@NotNull PsiMethod method) { + if (method instanceof JetClsMethod) { + JetDeclaration declaration = ((JetClsMethod) method).getOrigin(); + BindingContext bindingContext = + AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) declaration.getContainingFile()).getBindingContext(); + DeclarationDescriptor descriptor = + bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration); + if (descriptor != null) return JetRefactoringUtil.formatFunctionDescriptor(descriptor); + } + return JetRefactoringUtil.formatPsiMethod(method, false, false); + } + public interface SelectExpressionCallback { void run(@Nullable JetExpression expression); } diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/KotlinOverridingDialog.java b/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/KotlinOverridingDialog.java index 41d28e9051c..82fef3db618 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/KotlinOverridingDialog.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/KotlinOverridingDialog.java @@ -38,6 +38,7 @@ import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.plugin.JetBundle; import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; +import org.jetbrains.jet.plugin.refactoring.JetRefactoringUtil; import org.jetbrains.jet.renderer.DescriptorRenderer; import javax.swing.*; @@ -104,7 +105,7 @@ class KotlinOverridingDialog extends DialogWrapper { assert element instanceof PsiMethod : "Method accepts only kotlin functions/properties and java methods, but '" + element.getText() + "' was found"; - return KotlinSafeDeleteProcessor.formatPsiMethod((PsiMethod) element, true, false); + return JetRefactoringUtil.formatPsiMethod((PsiMethod) element, true, false); } @Override diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/KotlinSafeDeleteProcessor.java b/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/KotlinSafeDeleteProcessor.java index 7bfad45842d..0887d49a8bf 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/KotlinSafeDeleteProcessor.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/KotlinSafeDeleteProcessor.java @@ -22,13 +22,10 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.search.searches.OverridingMethodsSearch; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.MethodSignatureUtil; -import com.intellij.psi.util.PsiFormatUtil; -import com.intellij.psi.util.PsiFormatUtilBase; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.safeDelete.JavaSafeDeleteProcessor; import com.intellij.refactoring.safeDelete.NonCodeUsageSearchInfo; @@ -38,7 +35,6 @@ import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceJavaDele import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceSimpleDeleteUsageInfo; import com.intellij.usageView.UsageInfo; import com.intellij.util.ArrayUtilRt; -import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; @@ -55,7 +51,7 @@ import org.jetbrains.jet.lang.resolve.java.JetClsMethod; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.plugin.JetBundle; import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; -import org.jetbrains.jet.renderer.DescriptorRenderer; +import org.jetbrains.jet.plugin.refactoring.JetRefactoringUtil; import java.util.*; @@ -598,87 +594,6 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor { return false; } - @NotNull - private static String wrapOrSkip(@NotNull String s, boolean inCode) { - return inCode ? "" + s + "" : s; - } - - @NotNull - private static String formatClass( - @NotNull DeclarationDescriptor classDescriptor, - @NotNull BindingContext bindingContext, - boolean inCode - ) { - PsiElement element = BindingContextUtils.descriptorToDeclaration(bindingContext, classDescriptor); - if (element instanceof PsiClass) { - return formatPsiClass((PsiClass) element, false, inCode); - } - - return wrapOrSkip(formatClassDescriptor(classDescriptor), inCode); - } - - @NotNull - private static String formatFunction( - @NotNull DeclarationDescriptor functionDescriptor, - @NotNull BindingContext bindingContext, - boolean inCode - ) { - PsiElement element = BindingContextUtils.descriptorToDeclaration(bindingContext, functionDescriptor); - if (element instanceof PsiMethod) { - return formatPsiMethod((PsiMethod) element, false, inCode); - } - - return wrapOrSkip(formatFunctionDescriptor(functionDescriptor), inCode); - } - - @NotNull - private static String formatClassDescriptor(@NotNull DeclarationDescriptor classDescriptor) { - return DescriptorRenderer.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(classDescriptor); - } - - @NotNull - private static String formatFunctionDescriptor(@NotNull DeclarationDescriptor functionDescriptor) { - return DescriptorRenderer.COMPACT.render(functionDescriptor); - } - - @NotNull - public static String formatPsiClass( - @NotNull PsiClass psiClass, - boolean markAsJava, - boolean inCode - ) { - String description; - - String kind = psiClass.isInterface() ? "interface " : "class "; - description = kind + PsiFormatUtil.formatClass( - psiClass, - PsiFormatUtilBase.SHOW_CONTAINING_CLASS - | PsiFormatUtilBase.SHOW_NAME - | PsiFormatUtilBase.SHOW_PARAMETERS - | PsiFormatUtilBase.SHOW_TYPE - ); - description = wrapOrSkip(description, inCode); - - return markAsJava ? "[Java] " + description : description; - } - - @NotNull - public static String formatPsiMethod( - @NotNull PsiMethod psiMethod, - boolean showContainingClass, - boolean inCode) { - int options = PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS | PsiFormatUtilBase.SHOW_TYPE; - if (showContainingClass) { - //noinspection ConstantConditions - options |= PsiFormatUtilBase.SHOW_CONTAINING_CLASS; - } - - String description = PsiFormatUtil.formatMethod(psiMethod, PsiSubstitutor.EMPTY, options, PsiFormatUtilBase.SHOW_TYPE); - description = wrapOrSkip(description, inCode); - - return "[Java] " + description; - } - @Override @Nullable public Collection findConflicts(@NotNull PsiElement element, @NotNull PsiElement[] allElementsToDelete) { @@ -701,10 +616,10 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor { if (overridenDescriptor.getModality() == Modality.ABSTRACT) { String message = JetBundle.message( "x.implements.y", - formatFunction(callableDescriptor, bindingContext, true), - formatClass(callableDescriptor.getContainingDeclaration(), bindingContext, true), - formatFunction(overridenDescriptor, bindingContext, true), - formatClass(overridenDescriptor.getContainingDeclaration(), bindingContext, true) + JetRefactoringUtil.formatFunction(callableDescriptor, bindingContext, true), + JetRefactoringUtil.formatClass(callableDescriptor.getContainingDeclaration(), bindingContext, true), + JetRefactoringUtil.formatFunction(overridenDescriptor, bindingContext, true), + JetRefactoringUtil.formatClass(overridenDescriptor.getContainingDeclaration(), bindingContext, true) ); messages.add(message); } @@ -856,102 +771,6 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor { } } - @Nullable - private static Collection checkSuperMethods( - @NotNull JetDeclaration declaration, @Nullable Collection ignore - ) { - final BindingContext bindingContext = - AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) declaration.getContainingFile()).getBindingContext(); - - DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration); - if (!(declarationDescriptor instanceof CallableMemberDescriptor)) return null; - - CallableMemberDescriptor callableDescriptor = (CallableMemberDescriptor) declarationDescriptor; - Set overridenDescriptors = callableDescriptor.getOverriddenDescriptors(); - - Collection superMethods = ContainerUtil.map( - overridenDescriptors, - new Function() { - @Override - public PsiElement fun(CallableMemberDescriptor descriptor) { - return BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor); - } - } - ); - if (ignore != null) { - superMethods.removeAll(ignore); - } - - if (superMethods.isEmpty()) return Collections.singletonList(declaration); - - List superClasses = getClassDescriptions(bindingContext, superMethods); - return askUserForMethodsToSearch(declaration, callableDescriptor, superMethods, superClasses); - } - - @NotNull - private static Collection askUserForMethodsToSearch( - @NotNull JetDeclaration declaration, - @NotNull CallableMemberDescriptor callableDescriptor, - @NotNull Collection superMethods, - @NotNull List superClasses - ) { - String superClassesStr = "\n" + StringUtil.join(superClasses, ""); - String message = JetBundle.message( - "x.overrides.y.in.class.list", - DescriptorRenderer.COMPACT.render(callableDescriptor), - DescriptorRenderer.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(callableDescriptor.getContainingDeclaration()), - superClassesStr - ); - - int exitCode = Messages.showYesNoCancelDialog( - declaration.getProject(), message, IdeBundle.message("title.warning"), Messages.getQuestionIcon() - ); - switch (exitCode) { - case Messages.YES: - return superMethods; - case Messages.NO: - return Collections.singletonList(declaration); - default: - return Collections.emptyList(); - } - } - - @NotNull - private static List getClassDescriptions( - @NotNull final BindingContext bindingContext, @NotNull Collection superMethods - ) { - return ContainerUtil.map( - superMethods, - new Function() { - @Override - public String fun(PsiElement element) { - String description; - - 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); - } - else { - assert element instanceof PsiMethod; - - PsiClass psiClass = ((PsiMethod) element).getContainingClass(); - assert psiClass != null; - - description = formatPsiClass(psiClass, true, false); - } - - return " " + description + "\n"; - } - } - ); - } - @Nullable @Override public Collection getElementsToSearch( @@ -971,7 +790,7 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor { } if (element instanceof JetNamedFunction || element instanceof JetProperty) { - return checkSuperMethods((JetDeclaration) element, allElementsToDelete); + return JetRefactoringUtil.checkSuperMethods((JetDeclaration) element, allElementsToDelete); } return super.getElementsToSearch(element, module, allElementsToDelete); @@ -989,7 +808,7 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor { } String message = - JetBundle.message("delete.param.in.method.hierarchy", formatJavaOrLightMethod(method)); + JetBundle.message("delete.param.in.method.hierarchy", JetRefactoringUtil.formatJavaOrLightMethod(method)); int exitCode = Messages.showOkCancelDialog( parameter.getProject(), message, IdeBundle.message("title.warning"), Messages.getQuestionIcon() ); @@ -1032,19 +851,6 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor { return parametersToDelete; } - @NotNull - private static String formatJavaOrLightMethod(@NotNull PsiMethod method) { - if (method instanceof JetClsMethod) { - JetDeclaration declaration = ((JetClsMethod) method).getOrigin(); - BindingContext bindingContext = - AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) declaration.getContainingFile()).getBindingContext(); - DeclarationDescriptor descriptor = - bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration); - if (descriptor != null) return formatFunctionDescriptor(descriptor); - } - return formatPsiMethod(method, false, false); - } - private static void addParameter(@NotNull PsiMethod method, @NotNull Set result, int parameterIndex) { if (method instanceof JetClsMethod) { JetDeclaration declaration = ((JetClsMethod) method).getOrigin();