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
.ui
.ConflictsDialog
;
26 import com
.intellij
.refactoring
.util
.CommonRefactoringUtil
;
27 import com
.intellij
.refactoring
.util
.JavaDocPolicy
;
28 import com
.intellij
.refactoring
.util
.RefactoringHierarchyUtil
;
29 import com
.intellij
.refactoring
.util
.classMembers
.MemberInfo
;
30 import com
.intellij
.refactoring
.util
.classMembers
.MemberInfoStorage
;
31 import com
.intellij
.usageView
.UsageViewUtil
;
32 import com
.intellij
.util
.IncorrectOperationException
;
33 import org
.jetbrains
.annotations
.NotNull
;
35 import java
.util
.ArrayList
;
36 import java
.util
.List
;
38 public class PullUpHandler
implements RefactoringActionHandler
, PullUpDialog
.Callback
{
39 private static final Logger LOG
= Logger
.getInstance("#com.intellij.refactoring.memberPullUp.PullUpHandler");
40 public static final String REFACTORING_NAME
= RefactoringBundle
.message("pull.members.up.title");
41 private PsiClass mySubclass
;
42 private Project myProject
;
44 public void invoke(@NotNull Project project
, Editor editor
, PsiFile file
, DataContext dataContext
) {
45 int offset
= editor
.getCaretModel().getOffset();
46 editor
.getScrollingModel().scrollToCaret(ScrollType
.MAKE_VISIBLE
);
47 PsiElement element
= file
.findElementAt(offset
);
50 if (element
== null || element
instanceof PsiFile
) {
51 String message
= RefactoringBundle
52 .getCannotRefactorMessage(RefactoringBundle
.message("the.caret.should.be.positioned.inside.a.class.to.pull.members.from"));
53 CommonRefactoringUtil
.showErrorHint(project
, editor
, message
, REFACTORING_NAME
, HelpID
.MEMBERS_PULL_UP
);
57 if (!CommonRefactoringUtil
.checkReadOnlyStatus(project
, element
)) return;
59 if (element
instanceof PsiClass
|| element
instanceof PsiField
|| element
instanceof PsiMethod
) {
60 invoke(project
, new PsiElement
[]{element
}, dataContext
);
63 element
= element
.getParent();
67 public void invoke(@NotNull final Project project
, @NotNull PsiElement
[] elements
, DataContext dataContext
) {
68 if (elements
.length
!= 1) return;
71 PsiElement element
= elements
[0];
73 PsiElement aMember
= null;
75 if (element
instanceof PsiClass
) {
76 aClass
= (PsiClass
)element
;
78 else if (element
instanceof PsiMethod
) {
79 aClass
= ((PsiMethod
)element
).getContainingClass();
82 else if (element
instanceof PsiField
) {
83 aClass
= ((PsiField
)element
).getContainingClass();
90 Editor editor
= PlatformDataKeys
.EDITOR
.getData(dataContext
);
93 RefactoringBundle
.getCannotRefactorMessage(RefactoringBundle
.message("is.not.supported.in.the.current.context", REFACTORING_NAME
));
94 CommonRefactoringUtil
.showErrorHint(project
, editor
, message
, REFACTORING_NAME
, HelpID
.MEMBERS_PULL_UP
);
98 ArrayList
<PsiClass
> bases
= RefactoringHierarchyUtil
.createBasesList(aClass
, false, true);
100 if (bases
.isEmpty()) {
101 String message
= RefactoringBundle
.getCannotRefactorMessage(
102 RefactoringBundle
.message("class.does.not.have.base.classes.interfaces.in.current.project", aClass
.getQualifiedName()));
103 CommonRefactoringUtil
.showErrorHint(project
, editor
, message
, REFACTORING_NAME
, HelpID
.MEMBERS_PULL_UP
);
109 MemberInfoStorage memberInfoStorage
= new MemberInfoStorage(mySubclass
, new MemberInfo
.Filter() {
110 public boolean includeMember(PsiMember element
) {
114 List
<MemberInfo
> members
= memberInfoStorage
.getClassMemberInfos(mySubclass
);
115 PsiManager manager
= mySubclass
.getManager();
117 for (MemberInfo member
: members
) {
118 if (manager
.areElementsEquivalent(member
.getMember(), aMember
)) {
119 member
.setChecked(true);
124 final PullUpDialog dialog
= new PullUpDialog(project
, aClass
, bases
, memberInfoStorage
, this);
129 if (!dialog
.isOK()) return;
131 CommandProcessor
.getInstance().executeCommand(myProject
, new Runnable() {
133 final Runnable action
= new Runnable() {
135 doRefactoring(dialog
);
138 ApplicationManager
.getApplication().runWriteAction(action
);
140 }, REFACTORING_NAME
, null);
145 private void doRefactoring(PullUpDialog dialog
) {
146 LocalHistoryAction a
= LocalHistory
.startAction(myProject
, getCommandName());
149 PullUpHelper helper
= new PullUpHelper(mySubclass
, dialog
.getSuperClass(), dialog
.getSelectedMemberInfos(),
150 new JavaDocPolicy(dialog
.getJavaDocPolicy()));
151 helper
.moveMembersToBase();
152 helper
.moveFieldInitializations();
158 catch (IncorrectOperationException e
) {
163 private String
getCommandName() {
164 return RefactoringBundle
.message("pullUp.command", UsageViewUtil
.getDescriptiveName(mySubclass
));
167 public boolean checkConflicts(PullUpDialog dialog
) {
168 final MemberInfo
[] infos
= dialog
.getSelectedMemberInfos();
169 PsiClass superClass
= dialog
.getSuperClass();
170 if (!checkWritable(superClass
, infos
)) return false;
171 String
[] conflicts
= PullUpConflictsUtil
.checkConflicts(infos
, mySubclass
, superClass
, null, null, dialog
.getContainmentVerifier());
172 if (conflicts
.length
> 0) {
173 ConflictsDialog conflictsDialog
= new ConflictsDialog(myProject
, conflicts
);
174 conflictsDialog
.show();
175 return conflictsDialog
.isOK();
180 private boolean checkWritable(PsiClass superClass
, MemberInfo
[] infos
) {
181 if (!CommonRefactoringUtil
.checkReadOnlyStatus(myProject
, superClass
)) return false;
182 for (MemberInfo info
: infos
) {
183 if (info
.getMember() instanceof PsiClass
&& info
.getOverrides() != null) continue;
184 if (!CommonRefactoringUtil
.checkReadOnlyStatus(myProject
, info
.getMember())) return false;