Generate delegate methods action moved to lang-impl: take 2

This commit is contained in:
Kirill.Safonov
2010-09-26 17:11:59 +04:00
parent 8f7db00188
commit 47755aef4b
8 changed files with 131 additions and 41 deletions
@@ -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<PsiGenerationInfo<PsiMethod>> prototypes = new ArrayList<PsiGenerationInfo<PsiMethod>>(candidates.length);
for (PsiMethodMember candidate : candidates) {
prototypes.add(generateDelegatePrototype(candidate, target));
@@ -71,7 +110,7 @@ public class GenerateDelegateHandler implements CodeInsightActionHandler {
List<PsiGenerationInfo<PsiMethod>> 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<PsiMethod> 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<PsiMethodMember> methodInstances = new ArrayList<PsiMethodMember>();
@@ -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<PsiElementClassMember> chooser = new MemberChooser<PsiElementClassMember>(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<PsiElementClassMember> result = new ArrayList<PsiElementClassMember>();
@@ -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);
@@ -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;
@@ -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;
}
}
@@ -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();
}
}
@@ -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
@@ -28,6 +28,7 @@
<group id="GenerateGroup">
<action id="OverrideMethods" class="com.intellij.codeInsight.generation.actions.OverrideMethodsAction"/>
<action id="ImplementMethods" class="com.intellij.codeInsight.generation.actions.ImplementMethodsAction"/>
<action id="DelegateMethods" class="com.intellij.refactoring.actions.GenerateDelegateAction"/>
</group>
<action id="ShowIntentionActions" class="com.intellij.codeInsight.intention.actions.ShowIntentionActionsAction"/>
-1
View File
@@ -41,7 +41,6 @@
</group>
<group id="JavaGenerateGroup2">
<action id="DelegateMethods" class="com.intellij.codeInsight.generation.actions.GenerateDelegateAction"/>
<action id="GenerateSuperMethodCall" class="com.intellij.codeInsight.generation.actions.GenerateSuperMethodCallAction"/>
<add-to-group group-id="GenerateGroup" anchor="last"/>