2 * Copyright 2000-2010 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.intellij.refactoring.changeSignature;
18 import com.intellij.codeInsight.TargetElementUtil;
19 import com.intellij.ide.util.SuperMethodWarningUtil;
20 import com.intellij.openapi.actionSystem.DataContext;
21 import com.intellij.openapi.actionSystem.LangDataKeys;
22 import com.intellij.openapi.actionSystem.PlatformDataKeys;
23 import com.intellij.openapi.editor.Editor;
24 import com.intellij.openapi.editor.ScrollType;
25 import com.intellij.openapi.project.Project;
26 import com.intellij.psi.*;
27 import com.intellij.psi.util.PsiTreeUtil;
28 import com.intellij.refactoring.HelpID;
29 import com.intellij.refactoring.RefactoringBundle;
30 import com.intellij.refactoring.changeClassSignature.ChangeClassSignatureDialog;
31 import com.intellij.refactoring.util.CommonRefactoringUtil;
32 import org.jetbrains.annotations.NotNull;
33 import org.jetbrains.annotations.Nullable;
35 public class JavaChangeSignatureHandler implements ChangeSignatureHandler {
37 public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) {
38 editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
39 PsiElement element = findTargetMember(file, editor);
40 if (element == null) {
41 element = LangDataKeys.PSI_ELEMENT.getData(dataContext);
43 invokeOnElement(project, editor, element);
46 private static void invokeOnElement(Project project, Editor editor, PsiElement element) {
47 if (element instanceof PsiMethod) {
48 invoke((PsiMethod) element, project, editor);
50 else if (element instanceof PsiClass) {
51 invoke((PsiClass) element, editor);
54 String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("error.wrong.caret.position.method.or.class.name"));
55 CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.CHANGE_SIGNATURE);
59 public void invoke(@NotNull final Project project, @NotNull final PsiElement[] elements, final DataContext dataContext) {
60 if (elements.length != 1) return;
61 Editor editor = PlatformDataKeys.EDITOR.getData(dataContext);
62 invokeOnElement(project, editor, elements[0]);
65 private static void invoke(final PsiMethod method, final Project project, @Nullable final Editor editor) {
66 if (!CommonRefactoringUtil.checkReadOnlyStatus(project, method)) return;
68 PsiMethod newMethod = SuperMethodWarningUtil.checkSuperMethod(method, RefactoringBundle.message("to.refactor"));
69 if (newMethod == null) return;
71 if (!newMethod.equals(method)) {
72 invoke(newMethod, project, editor);
76 if (!CommonRefactoringUtil.checkReadOnlyStatus(project, method)) return;
78 final PsiClass containingClass = method.getContainingClass();
79 final PsiReferenceExpression refExpr = editor != null ? TargetElementUtil.findReferenceExpression(editor) : null;
80 final ChangeSignatureDialog dialog = new ChangeSignatureDialog(project, method, containingClass != null && !containingClass.isInterface(),
85 private static void invoke(final PsiClass aClass, Editor editor) {
86 final PsiTypeParameterList typeParameterList = aClass.getTypeParameterList();
87 Project project = aClass.getProject();
88 if (typeParameterList == null) {
89 final String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("changeClassSignature.no.type.parameters"));
90 CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.CHANGE_CLASS_SIGNATURE);
93 if (!CommonRefactoringUtil.checkReadOnlyStatus(project, aClass)) return;
95 ChangeClassSignatureDialog dialog = new ChangeClassSignatureDialog(aClass);
100 public PsiElement findTargetMember(PsiFile file, Editor editor) {
101 PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
102 return findTargetMember(element);
105 public PsiElement findTargetMember(PsiElement element) {
106 if (PsiTreeUtil.getParentOfType(element, PsiParameterList.class) != null) {
107 return PsiTreeUtil.getParentOfType(element, PsiMethod.class);
110 if (element.getParent() instanceof PsiMethod && ((PsiMethod)element.getParent()).getNameIdentifier()==element) {
111 return element.getParent();
114 final PsiMethodCallExpression expression = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression.class);
115 if (expression != null) {
116 assert element != null;
117 final PsiExpression qualifierExpression = expression.getMethodExpression().getQualifierExpression();
118 if (PsiTreeUtil.isAncestor(qualifierExpression, element, false)) {
119 final PsiExpressionList expressionList = PsiTreeUtil.getParentOfType(qualifierExpression, PsiExpressionList.class);
120 if (expressionList != null) {
121 final PsiElement parent = expressionList.getParent();
122 if (parent instanceof PsiMethodCallExpression) {
123 return ((PsiMethodCallExpression)parent).resolveMethod();
128 return expression.resolveMethod();
132 final PsiTypeParameterList typeParameterList = PsiTreeUtil.getParentOfType(element, PsiTypeParameterList.class);
133 if (typeParameterList != null) {
134 return PsiTreeUtil.getParentOfType(typeParameterList, PsiMember.class);
137 final PsiReferenceParameterList referenceParameterList = PsiTreeUtil.getParentOfType(element, PsiReferenceParameterList.class);
138 if (referenceParameterList != null) {
139 final PsiJavaCodeReferenceElement referenceElement =
140 PsiTreeUtil.getParentOfType(referenceParameterList, PsiJavaCodeReferenceElement.class);
141 if (referenceElement != null) {
142 final PsiElement resolved = referenceElement.resolve();
143 if (resolved instanceof PsiClass) {
146 else if (resolved instanceof PsiMethod) {