2 * Created by IntelliJ IDEA.
6 * To change template for new class use
7 * Code Style | Class Templates options (Tools | IDE Options).
9 package com
.intellij
.refactoring
.memberPullUp
;
11 import com
.intellij
.history
.LocalHistoryAction
;
12 import com
.intellij
.history
.LocalHistory
;
13 import com
.intellij
.openapi
.actionSystem
.DataContext
;
14 import com
.intellij
.openapi
.actionSystem
.PlatformDataKeys
;
15 import com
.intellij
.openapi
.application
.ApplicationManager
;
16 import com
.intellij
.openapi
.command
.CommandProcessor
;
17 import com
.intellij
.openapi
.diagnostic
.Logger
;
18 import com
.intellij
.openapi
.editor
.Editor
;
19 import com
.intellij
.openapi
.editor
.ScrollType
;
20 import com
.intellij
.openapi
.project
.Project
;
21 import com
.intellij
.psi
.*;
22 import com
.intellij
.refactoring
.HelpID
;
23 import com
.intellij
.refactoring
.RefactoringActionHandler
;
24 import com
.intellij
.refactoring
.RefactoringBundle
;
25 import com
.intellij
.refactoring
.lang
.ElementsHandler
;
26 import com
.intellij
.refactoring
.ui
.ConflictsDialog
;
27 import com
.intellij
.refactoring
.util
.CommonRefactoringUtil
;
28 import com
.intellij
.refactoring
.util
.JavaDocPolicy
;
29 import com
.intellij
.refactoring
.util
.RefactoringHierarchyUtil
;
30 import com
.intellij
.refactoring
.util
.classMembers
.MemberInfo
;
31 import com
.intellij
.refactoring
.util
.classMembers
.MemberInfoStorage
;
32 import com
.intellij
.usageView
.UsageViewUtil
;
33 import com
.intellij
.util
.IncorrectOperationException
;
34 import org
.jetbrains
.annotations
.NotNull
;
36 import java
.util
.ArrayList
;
37 import java
.util
.List
;
39 public class JavaPullUpHandler
implements RefactoringActionHandler
, PullUpDialog
.Callback
, ElementsHandler
{
40 private static final Logger LOG
= Logger
.getInstance("#com.intellij.refactoring.memberPullUp.JavaPullUpHandler");
41 public static final String REFACTORING_NAME
= RefactoringBundle
.message("pull.members.up.title");
42 private PsiClass mySubclass
;
43 private Project myProject
;
45 public void invoke(@NotNull Project project
, Editor editor
, PsiFile file
, DataContext dataContext
) {
46 int offset
= editor
.getCaretModel().getOffset();
47 editor
.getScrollingModel().scrollToCaret(ScrollType
.MAKE_VISIBLE
);
48 PsiElement element
= file
.findElementAt(offset
);
51 if (element
== null || element
instanceof PsiFile
) {
52 String message
= RefactoringBundle
53 .getCannotRefactorMessage(RefactoringBundle
.message("the.caret.should.be.positioned.inside.a.class.to.pull.members.from"));
54 CommonRefactoringUtil
.showErrorHint(project
, editor
, message
, REFACTORING_NAME
, HelpID
.MEMBERS_PULL_UP
);
58 if (!CommonRefactoringUtil
.checkReadOnlyStatus(project
, element
)) return;
60 if (element
instanceof PsiClass
|| element
instanceof PsiField
|| element
instanceof PsiMethod
) {
61 invoke(project
, new PsiElement
[]{element
}, dataContext
);
64 element
= element
.getParent();
68 public void invoke(@NotNull final Project project
, @NotNull PsiElement
[] elements
, DataContext dataContext
) {
69 if (elements
.length
!= 1) return;
72 PsiElement element
= elements
[0];
74 PsiElement aMember
= null;
76 if (element
instanceof PsiClass
) {
77 aClass
= (PsiClass
)element
;
79 else if (element
instanceof PsiMethod
) {
80 aClass
= ((PsiMethod
)element
).getContainingClass();
83 else if (element
instanceof PsiField
) {
84 aClass
= ((PsiField
)element
).getContainingClass();
91 Editor editor
= PlatformDataKeys
.EDITOR
.getData(dataContext
);
94 RefactoringBundle
.getCannotRefactorMessage(RefactoringBundle
.message("is.not.supported.in.the.current.context", REFACTORING_NAME
));
95 CommonRefactoringUtil
.showErrorHint(project
, editor
, message
, REFACTORING_NAME
, HelpID
.MEMBERS_PULL_UP
);
99 ArrayList
<PsiClass
> bases
= RefactoringHierarchyUtil
.createBasesList(aClass
, false, true);
101 if (bases
.isEmpty()) {
102 String message
= RefactoringBundle
.getCannotRefactorMessage(
103 RefactoringBundle
.message("class.does.not.have.base.classes.interfaces.in.current.project", aClass
.getQualifiedName()));
104 CommonRefactoringUtil
.showErrorHint(project
, editor
, message
, REFACTORING_NAME
, HelpID
.MEMBERS_PULL_UP
);
110 MemberInfoStorage memberInfoStorage
= new MemberInfoStorage(mySubclass
, new MemberInfo
.Filter() {
111 public boolean includeMember(PsiMember element
) {
115 List
<MemberInfo
> members
= memberInfoStorage
.getClassMemberInfos(mySubclass
);
116 PsiManager manager
= mySubclass
.getManager();
118 for (MemberInfo member
: members
) {
119 if (manager
.areElementsEquivalent(member
.getMember(), aMember
)) {
120 member
.setChecked(true);
125 final PullUpDialog dialog
= new PullUpDialog(project
, aClass
, bases
, memberInfoStorage
, this);
130 if (!dialog
.isOK()) return;
132 CommandProcessor
.getInstance().executeCommand(myProject
, new Runnable() {
134 final Runnable action
= new Runnable() {
136 doRefactoring(dialog
);
139 ApplicationManager
.getApplication().runWriteAction(action
);
141 }, REFACTORING_NAME
, null);
146 private void doRefactoring(PullUpDialog dialog
) {
147 LocalHistoryAction a
= LocalHistory
.startAction(myProject
, getCommandName());
150 PullUpHelper helper
= new PullUpHelper(mySubclass
, dialog
.getSuperClass(), dialog
.getSelectedMemberInfos(),
151 new JavaDocPolicy(dialog
.getJavaDocPolicy()));
152 helper
.moveMembersToBase();
153 helper
.moveFieldInitializations();
159 catch (IncorrectOperationException e
) {
164 private String
getCommandName() {
165 return RefactoringBundle
.message("pullUp.command", UsageViewUtil
.getDescriptiveName(mySubclass
));
168 public boolean checkConflicts(PullUpDialog dialog
) {
169 final MemberInfo
[] infos
= dialog
.getSelectedMemberInfos();
170 PsiClass superClass
= dialog
.getSuperClass();
171 if (!checkWritable(superClass
, infos
)) return false;
172 String
[] conflicts
= PullUpConflictsUtil
.checkConflicts(infos
, mySubclass
, superClass
, null, null, dialog
.getContainmentVerifier());
173 if (conflicts
.length
> 0) {
174 ConflictsDialog conflictsDialog
= new ConflictsDialog(myProject
, conflicts
);
175 conflictsDialog
.show();
176 return conflictsDialog
.isOK();
181 private boolean checkWritable(PsiClass superClass
, MemberInfo
[] infos
) {
182 if (!CommonRefactoringUtil
.checkReadOnlyStatus(myProject
, superClass
)) return false;
183 for (MemberInfo info
: infos
) {
184 if (info
.getMember() instanceof PsiClass
&& info
.getOverrides() != null) continue;
185 if (!CommonRefactoringUtil
.checkReadOnlyStatus(myProject
, info
.getMember())) return false;
190 public boolean isEnabledOnElements(PsiElement
[] elements
) {
192 if (elements.length == 1) {
193 return elements[0] instanceof PsiClass || elements[0] instanceof PsiField || elements[0] instanceof PsiMethod;
195 else if (elements.length > 1){
196 for (int idx = 0; idx < elements.length; idx++) {
197 PsiElement element = elements[idx];
198 if (!(element instanceof PsiField || element instanceof PsiMethod)) return false;
204 // todo: multiple selection etc
205 return elements
.length
== 1 && elements
[0] instanceof PsiClass
;