ability to change name of method to any string constant. Detection of incorrect usages
[idea/community.git] / plugins / groovy / src / org / jetbrains / plugins / groovy / refactoring / changeSignature / GrChangeSignatureHandler.java
1 /*
2  * Copyright 2000-2010 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.jetbrains.plugins.groovy.refactoring.changeSignature;
17
18 import com.intellij.ide.util.SuperMethodWarningUtil;
19 import com.intellij.openapi.actionSystem.DataContext;
20 import com.intellij.openapi.actionSystem.LangDataKeys;
21 import com.intellij.openapi.actionSystem.PlatformDataKeys;
22 import com.intellij.openapi.editor.Editor;
23 import com.intellij.openapi.editor.ScrollType;
24 import com.intellij.openapi.project.Project;
25 import com.intellij.psi.PsiElement;
26 import com.intellij.psi.PsiFile;
27 import com.intellij.psi.PsiMethod;
28 import com.intellij.psi.PsiReference;
29 import com.intellij.psi.util.PsiTreeUtil;
30 import com.intellij.refactoring.HelpID;
31 import com.intellij.refactoring.RefactoringBundle;
32 import com.intellij.refactoring.changeSignature.ChangeSignatureHandler;
33 import com.intellij.refactoring.util.CommonRefactoringUtil;
34 import org.jetbrains.annotations.NotNull;
35 import org.jetbrains.annotations.Nullable;
36 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
37 import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList;
38 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
39 import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle;
40
41 /**
42  * @author Maxim.Medvedev
43  */
44 public class GrChangeSignatureHandler implements ChangeSignatureHandler {
45
46   public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) {
47     editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
48     PsiElement element = findTargetMember(file, editor);
49     if (element == null) {
50       element = LangDataKeys.PSI_ELEMENT.getData(dataContext);
51     }
52     invokeOnElement(project, editor, element);
53   }
54
55   private static void invokeOnElement(Project project, Editor editor, PsiElement element) {
56     if (element instanceof PsiMethod) {
57       invoke((PsiMethod)element, project, editor);
58     }
59     else {
60       String message =
61         RefactoringBundle.getCannotRefactorMessage(GroovyRefactoringBundle.message("error.wrong.caret.position.method.name"));
62       CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.CHANGE_SIGNATURE);
63     }
64   }
65
66   public void invoke(@NotNull final Project project, @NotNull final PsiElement[] elements, final DataContext dataContext) {
67     if (elements.length != 1) return;
68     Editor editor = PlatformDataKeys.EDITOR.getData(dataContext);
69     invokeOnElement(project, editor, elements[0]);
70   }
71
72   private static void invoke(final PsiMethod method, final Project project, @Nullable final Editor editor) {
73     if (!CommonRefactoringUtil.checkReadOnlyStatus(project, method)) return;
74
75     PsiMethod newMethod = SuperMethodWarningUtil.checkSuperMethod(method, RefactoringBundle.message("to.refactor"));
76     if (newMethod == null) return;
77
78     if (!newMethod.equals(method)) {
79       invoke(newMethod, project, editor);
80       return;
81     }
82
83     if (!CommonRefactoringUtil.checkReadOnlyStatus(project, method)) return;
84
85     if (!(method instanceof GrMethod)) return; //todo
86     final GrChangeSignatureDialog dialog = new GrChangeSignatureDialog(project, (GrMethod)method);
87     dialog.show();
88   }
89
90   @Nullable
91   public PsiElement findTargetMember(PsiFile file, Editor editor) {
92     final PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
93     final PsiElement targetMember = findTargetMember(element);
94     if (targetMember != null) return targetMember;
95
96     final PsiReference reference = file.findReferenceAt(editor.getCaretModel().getOffset());
97     if (reference != null) {
98       return reference.resolve();
99     }
100     return null;
101   }
102
103   @Nullable
104   public PsiElement findTargetMember(PsiElement element) {
105     final GrParameterList parameterList = PsiTreeUtil.getParentOfType(element, GrParameterList.class);
106     if (parameterList != null) {
107       final PsiElement parent = parameterList.getParent();
108       if (parent instanceof PsiMethod) return parent;
109     }
110
111     if (element.getParent() instanceof GrMethod && ((GrMethod)element.getParent()).getNameIdentifierGroovy() == element) {
112       return element.getParent();
113     }
114     final GrMethodCallExpression expression = PsiTreeUtil.getParentOfType(element, GrMethodCallExpression.class);
115     if (expression != null) {
116       return expression.resolveMethod();
117     }
118
119     final PsiReference ref = element.getReference();
120     if (ref == null) return null;
121     return ref.resolve();
122   }
123 }