From 47755aef4bdd7c9be6d07681ee0dd163e5ca81bd Mon Sep 17 00:00:00 2001 From: "Kirill.Safonov" Date: Sun, 26 Sep 2010 17:03:00 +0400 Subject: [PATCH] Generate delegate methods action moved to lang-impl: take 2 --- .../generation/GenerateDelegateHandler.java | 101 ++++++++++++++---- .../generation/OverrideImplementUtil.java | 6 +- .../java/JavaRefactoringSupportProvider.java | 6 ++ .../RefactoringSupportProvider.java | 9 ++ .../actions/GenerateDelegateAction.java | 47 +++++--- .../src/messages/RefactoringBundle.properties | 1 + .../src/idea/LangActions.xml | 1 + resources/src/idea/IdeaActions.xml | 1 - 8 files changed, 131 insertions(+), 41 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java index 741a9f0b7eb6..4fe331dd2678 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java @@ -15,11 +15,13 @@ */ package com.intellij.codeInsight.generation; -import com.intellij.codeInsight.CodeInsightActionHandler; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.ide.util.MemberChooser; +import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ScrollType; import com.intellij.openapi.fileEditor.FileDocumentManager; @@ -28,6 +30,8 @@ import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.util.*; +import com.intellij.refactoring.RefactoringBundle; +import com.intellij.refactoring.lang.ElementsHandler; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.HashSet; @@ -43,27 +47,62 @@ import java.util.Set; /** * @author mike */ -public class GenerateDelegateHandler implements CodeInsightActionHandler { +public class GenerateDelegateHandler implements ElementsHandler { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.generation.GenerateDelegateHandler"); - public void invoke(@NotNull final Project project, @NotNull final Editor editor, @NotNull final PsiFile file) { - if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), project)) { + @Override + public boolean isEnabledOnElements(PsiElement[] elements) { + if (elements.length != 1) return false; + if (!(elements[0].getContainingFile() instanceof PsiJavaFile)) return false; + return OverrideImplementUtil.getContextClass(elements[0], false) != null && isApplicable(elements[0]); + } + + @Override + public void invoke(@NotNull Project project, @NotNull PsiElement[] elements, DataContext dataContext) { + doInvoke(project, null, elements[0].getContainingFile(), elements[0]); + } + + @Override + public void invoke(@NotNull Project project, final Editor editor, final PsiFile file, DataContext dataContext) { + doInvoke(project, editor, file, null); + } + + private void doInvoke(@NotNull Project project, @Nullable final Editor editor, final PsiFile file, @Nullable PsiElement element) { + Document document; + if (editor != null) { + document = editor.getDocument(); + } + else { + document = PsiDocumentManager.getInstance(project).getDocument(file); + } + if (!FileDocumentManager.getInstance().requestWriting(document, project)) { return; } PsiDocumentManager.getInstance(project).commitAllDocuments(); - final PsiElement target = chooseTarget(file, editor, project); + final PsiElement target; + if (editor != null) { + target = chooseTarget(file, editor, project); + int offset = editor.getCaretModel().getOffset(); + element = file.findElementAt(offset); + } else { + target = chooseTarget(element); + } if (target == null) return; - final PsiMethodMember[] candidates = chooseMethods(target, file, editor, project); + final PsiMethodMember[] candidates = chooseMethods(target, element, project); if (candidates == null || candidates.length == 0) return; + final int offset; + if (editor != null) { + offset = editor.getCaretModel().getOffset(); + } else { + offset = element.getTextRange().getStartOffset(); + } - ApplicationManager.getApplication().runWriteAction(new Runnable() { + final Runnable r = new Runnable() { public void run() { try { - int offset = editor.getCaretModel().getOffset(); - List> prototypes = new ArrayList>(candidates.length); for (PsiMethodMember candidate : candidates) { prototypes.add(generateDelegatePrototype(candidate, target)); @@ -71,7 +110,7 @@ public class GenerateDelegateHandler implements CodeInsightActionHandler { List> results = GenerateMembersUtil.insertMembersAtOffset(file, offset, prototypes); - if (!results.isEmpty()) { + if (!results.isEmpty() && editor != null) { PsiMethod firstMethod = results.get(0).getPsiMember(); final PsiCodeBlock block = firstMethod.getBody(); assert block != null; @@ -86,11 +125,15 @@ public class GenerateDelegateHandler implements CodeInsightActionHandler { LOG.error(e); } } - }); - } + }; + + CommandProcessor.getInstance().executeCommand(project, new Runnable() { + public void run() { + ApplicationManager.getApplication().runWriteAction(r); + } + }, RefactoringBundle.message("delegate.methods.refactoring.name"), null); + - public boolean startInWriteAction() { - return false; } private static PsiGenerationInfo generateDelegatePrototype(PsiMethodMember methodCandidate, PsiElement target) throws IncorrectOperationException { @@ -190,7 +233,7 @@ public class GenerateDelegateHandler implements CodeInsightActionHandler { } @Nullable - private static PsiMethodMember[] chooseMethods(PsiElement target, PsiFile file, Editor editor, Project project) { + private static PsiMethodMember[] chooseMethods(PsiElement target, PsiElement element, Project project) { PsiClassType.ClassResolveResult resolveResult = null; if (target instanceof PsiField) { @@ -204,10 +247,8 @@ public class GenerateDelegateHandler implements CodeInsightActionHandler { PsiClass targetClass = resolveResult.getElement(); PsiSubstitutor substitutor = resolveResult.getSubstitutor(); - int offset = editor.getCaretModel().getOffset(); - PsiElement element = file.findElementAt(offset); if (element == null) return null; - PsiClass aClass = PsiTreeUtil.getParentOfType(element, PsiClass.class); + PsiClass aClass = PsiTreeUtil.getParentOfType(element, PsiClass.class, false); if (aClass == null) return null; List methodInstances = new ArrayList(); @@ -254,16 +295,28 @@ public class GenerateDelegateHandler implements CodeInsightActionHandler { return result; } - public static boolean isApplicable(PsiFile file, Editor editor) { - ClassMember[] targetElements = getTargetElements(file, editor); + private static boolean isApplicable(PsiElement element) { + ClassMember[] targetElements = getTargetElements(element); return targetElements != null && targetElements.length > 0; } @Nullable private static PsiElement chooseTarget(PsiFile file, Editor editor, Project project) { - PsiElement target = null; final PsiElementClassMember[] targetElements = getTargetElements(file, editor); + return doChooseTarget(project, targetElements); + } + + @Nullable + private static PsiElement chooseTarget(PsiElement element) { + final PsiElementClassMember[] targetElements = getTargetElements(element); + return doChooseTarget(element.getProject(), targetElements); + } + + @Nullable + private static PsiElement doChooseTarget(Project project, PsiElementClassMember[] targetElements) { if (targetElements == null || targetElements.length == 0) return null; + + PsiElement target = null; if (!ApplicationManager.getApplication().isUnitTestMode()) { MemberChooser chooser = new MemberChooser(targetElements, false, false, project); chooser.setTitle(CodeInsightBundle.message("generate.delegate.target.chooser.title")); @@ -287,7 +340,11 @@ public class GenerateDelegateHandler implements CodeInsightActionHandler { int offset = editor.getCaretModel().getOffset(); PsiElement element = file.findElementAt(offset); if (element == null) return null; - PsiClass aClass = PsiTreeUtil.getParentOfType(element, PsiClass.class); + return getTargetElements(element); + } + + private static PsiElementClassMember[] getTargetElements(PsiElement element) { + PsiClass aClass = PsiTreeUtil.getParentOfType(element, PsiClass.class, false); if (aClass == null) return null; List result = new ArrayList(); diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java b/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java index 8cf1df4453f3..ed9e5142ad7f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java @@ -696,8 +696,12 @@ public class OverrideImplementUtil { int offset = editor.getCaretModel().getOffset(); PsiElement element = file.findElementAt(offset); + return getContextClass(element, allowInterface); + } + + public static PsiClass getContextClass(PsiElement element, boolean allowInterface) { do { - element = PsiTreeUtil.getParentOfType(element, PsiClass.class); + element = PsiTreeUtil.getParentOfType(element, PsiClass.class, false); } while (element instanceof PsiTypeParameter); diff --git a/java/java-impl/src/com/intellij/lang/java/JavaRefactoringSupportProvider.java b/java/java-impl/src/com/intellij/lang/java/JavaRefactoringSupportProvider.java index e14e175978ce..50b41f00d1c6 100644 --- a/java/java-impl/src/com/intellij/lang/java/JavaRefactoringSupportProvider.java +++ b/java/java-impl/src/com/intellij/lang/java/JavaRefactoringSupportProvider.java @@ -15,6 +15,7 @@ */ package com.intellij.lang.java; +import com.intellij.codeInsight.generation.GenerateDelegateHandler; import com.intellij.lang.refactoring.RefactoringSupportProvider; import com.intellij.psi.*; import com.intellij.psi.javadoc.PsiDocComment; @@ -97,6 +98,11 @@ public class JavaRefactoringSupportProvider extends RefactoringSupportProvider { return new ExtractClassHandler(); } + @Override + public RefactoringActionHandler getGenerateDelegateHander() { + return new GenerateDelegateHandler(); + } + public static boolean mayRenameInplace(PsiElement elementToRename, final PsiElement nameSuggestionContext) { if (!(elementToRename instanceof PsiVariable)) return false; if (nameSuggestionContext != null && nameSuggestionContext.getContainingFile() != elementToRename.getContainingFile()) return false; diff --git a/platform/lang-api/src/com/intellij/lang/refactoring/RefactoringSupportProvider.java b/platform/lang-api/src/com/intellij/lang/refactoring/RefactoringSupportProvider.java index 6cf28083cb2a..6e3efe738214 100644 --- a/platform/lang-api/src/com/intellij/lang/refactoring/RefactoringSupportProvider.java +++ b/platform/lang-api/src/com/intellij/lang/refactoring/RefactoringSupportProvider.java @@ -133,4 +133,13 @@ public abstract class RefactoringSupportProvider { public RefactoringActionHandler getExtractClassHandler() { return null; } + + /** + * @return handler for generating delegate methods in this language + * @see com.intellij.refactoring.RefactoringActionHandler + */ + @Nullable + public RefactoringActionHandler getGenerateDelegateHander() { + return null; + } } diff --git a/platform/lang-impl/src/com/intellij/refactoring/actions/GenerateDelegateAction.java b/platform/lang-impl/src/com/intellij/refactoring/actions/GenerateDelegateAction.java index 63a2fc4c7abb..fe3e231235e2 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/actions/GenerateDelegateAction.java +++ b/platform/lang-impl/src/com/intellij/refactoring/actions/GenerateDelegateAction.java @@ -13,30 +13,43 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.codeInsight.generation.actions; +package com.intellij.refactoring.actions; -import com.intellij.codeInsight.CodeInsightActionHandler; -import com.intellij.codeInsight.actions.BaseCodeInsightAction; -import com.intellij.codeInsight.generation.GenerateDelegateHandler; -import com.intellij.codeInsight.generation.OverrideImplementUtil; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiJavaFile; +import com.intellij.lang.Language; +import com.intellij.lang.LanguageRefactoringSupport; +import com.intellij.lang.refactoring.RefactoringSupportProvider; +import com.intellij.psi.PsiElement; +import com.intellij.refactoring.RefactoringActionHandler; +import com.intellij.refactoring.lang.ElementsHandler; +import org.jetbrains.annotations.NotNull; /** * @author mike */ -public class GenerateDelegateAction extends BaseCodeInsightAction { - private final GenerateDelegateHandler myHandler = new GenerateDelegateHandler(); +public class GenerateDelegateAction extends BasePlatformRefactoringAction { - protected CodeInsightActionHandler getHandler() { - return myHandler; + public GenerateDelegateAction() { + setInjectedContext(true); } - protected boolean isValidForFile(Project project, Editor editor, PsiFile file) { - if (!(file instanceof PsiJavaFile)) return false; - return OverrideImplementUtil.getContextClass(project, editor, file, false) != null && - myHandler.isApplicable(file, editor); + @Override + protected boolean isAvailableInEditorOnly() { + return false; } + + @Override + public boolean isEnabledOnElements(PsiElement[] elements) { + if (elements.length > 0) { + final Language language = elements[0].getLanguage(); + final RefactoringActionHandler handler = getRefactoringHandler(LanguageRefactoringSupport.INSTANCE.forLanguage(language)); + return handler instanceof ElementsHandler && ((ElementsHandler)handler).isEnabledOnElements(elements); + } + return false; + } + + @Override + protected RefactoringActionHandler getRefactoringHandler(@NotNull RefactoringSupportProvider provider) { + return provider.getGenerateDelegateHander(); + } + } diff --git a/platform/platform-resources-en/src/messages/RefactoringBundle.properties b/platform/platform-resources-en/src/messages/RefactoringBundle.properties index 318b94f946c5..dd014c726970 100644 --- a/platform/platform-resources-en/src/messages/RefactoringBundle.properties +++ b/platform/platform-resources-en/src/messages/RefactoringBundle.properties @@ -742,3 +742,4 @@ refactoring.extract.method.dialog.empty=Empty change.signature.leave.blank.default.value=Leave &blank change.signature.feel.lucky=Feel &lucky change.signature.use.selected.value=Use selected &value +delegate.methods.refactoring.name=Delegate methods diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index 4875c00769f5..54103fc45b87 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -28,6 +28,7 @@ + diff --git a/resources/src/idea/IdeaActions.xml b/resources/src/idea/IdeaActions.xml index 5dbc91ed6b58..10bb54ab0b1d 100644 --- a/resources/src/idea/IdeaActions.xml +++ b/resources/src/idea/IdeaActions.xml @@ -41,7 +41,6 @@ -