(no message)
[fedora-idea.git] / refactoring / impl / com / intellij / refactoring / inline / InlineMethodHandler.java
blobbb445dbeb844772d04ce7e34c4c2010f16c1a2b2
2 package com.intellij.refactoring.inline;
4 import com.intellij.codeInsight.TargetElementUtil;
5 import com.intellij.openapi.editor.Editor;
6 import com.intellij.openapi.project.Project;
7 import com.intellij.openapi.vfs.ReadonlyStatusHandler;
8 import com.intellij.openapi.vfs.VirtualFile;
9 import com.intellij.psi.*;
10 import com.intellij.refactoring.HelpID;
11 import com.intellij.refactoring.RefactoringBundle;
12 import com.intellij.refactoring.util.RefactoringUtil;
13 import com.intellij.refactoring.util.CommonRefactoringUtil;
15 class InlineMethodHandler {
16 private static final String REFACTORING_NAME = RefactoringBundle.message("inline.method.title");
18 public void invoke(final Project project, Editor editor, PsiMethod method) {
19 method = (PsiMethod)method.getNavigationElement();
20 if (method.getBody() == null){
21 String message;
22 if (method.hasModifierProperty(PsiModifier.ABSTRACT)) {
23 message = RefactoringBundle.message("refactoring.cannot.be.applied.to.abstract.methods", REFACTORING_NAME);
25 else {
26 message = RefactoringBundle.message("refactoring.cannot.be.applied.no.sources.attached", REFACTORING_NAME);
28 CommonRefactoringUtil.showErrorMessage(REFACTORING_NAME, message, HelpID.INLINE_METHOD, project);
29 return;
32 if (InlineMethodProcessor.checkBadReturns(method)) {
33 String message = RefactoringBundle.message("refactoring.is.not.supported.when.return.statement.interrupts.the.execution.flow", REFACTORING_NAME);
34 CommonRefactoringUtil.showErrorMessage(REFACTORING_NAME, message, HelpID.INLINE_METHOD, project);
35 return;
38 PsiReference reference = editor != null ? TargetElementUtil.findReference(editor, editor.getCaretModel().getOffset()) : null;
39 if (reference == null && checkRecursive(method)) {
40 String message = RefactoringBundle.message("refactoring.is.not.supported.for.recursive.methods", REFACTORING_NAME);
41 CommonRefactoringUtil.showErrorMessage(REFACTORING_NAME, message, HelpID.INLINE_METHOD, project);
42 return;
45 if (method.isConstructor()) {
46 if (method.isVarArgs()) {
47 String message = RefactoringBundle.message("refactoring.cannot.be.applied.to.vararg.constructors", REFACTORING_NAME);
48 CommonRefactoringUtil.showErrorMessage(REFACTORING_NAME, message, HelpID.INLINE_METHOD, project);
49 return;
51 if (!checkChainingConstructor(method)) {
52 String message = RefactoringBundle.message("refactoring.cannot.be.applied.to.inline.non.chaining.constructors", REFACTORING_NAME);
53 CommonRefactoringUtil.showErrorMessage(REFACTORING_NAME, message, HelpID.INLINE_METHOD, project);
54 return;
56 if (reference != null) {
57 PsiCall constructorCall = RefactoringUtil.getEnclosingConstructorCall((PsiJavaCodeReferenceElement)reference.getElement());
58 if (constructorCall == null || !method.equals(constructorCall.resolveMethod())) reference = null;
61 else {
62 if (reference != null && !method.getManager().areElementsEquivalent(method, reference.resolve())) {
63 reference = null;
67 final boolean invokedOnReference = reference != null;
68 if (!invokedOnReference) {
69 final VirtualFile vFile = method.getContainingFile().getVirtualFile();
70 ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(vFile);
72 PsiJavaCodeReferenceElement refElement = reference != null ? (PsiJavaCodeReferenceElement)reference.getElement() : null;
73 InlineMethodDialog dialog = new InlineMethodDialog(project, method, refElement, editor);
74 dialog.show();
77 private static boolean checkChainingConstructor(PsiMethod constructor) {
78 PsiCodeBlock body = constructor.getBody();
79 if (body != null) {
80 PsiStatement[] statements = body.getStatements();
81 if (statements.length == 1 && statements[0] instanceof PsiExpressionStatement) {
82 PsiExpression expression = ((PsiExpressionStatement)statements[0]).getExpression();
83 if (expression instanceof PsiMethodCallExpression) {
84 PsiReferenceExpression methodExpr = ((PsiMethodCallExpression)expression).getMethodExpression();
85 if ("this".equals(methodExpr.getReferenceName())) {
86 PsiElement resolved = methodExpr.resolve();
87 return resolved instanceof PsiMethod && ((PsiMethod)resolved).isConstructor(); //delegated via "this" call
92 return false;
95 public static boolean checkRecursive(PsiMethod method) {
96 return checkCalls(method.getBody(), method);
99 private static boolean checkCalls(PsiElement scope, PsiMethod method) {
100 if (scope instanceof PsiMethodCallExpression){
101 PsiMethod refMethod = (PsiMethod)((PsiMethodCallExpression)scope).getMethodExpression().resolve();
102 if (method.equals(refMethod)) return true;
105 for(PsiElement child = scope.getFirstChild(); child != null; child = child.getNextSibling()){
106 if (checkCalls(child, method)) return true;
109 return false;