2 * Copyright 2000-2009 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
.codeInsight
.daemon
.impl
.quickfix
;
18 import com
.intellij
.codeInsight
.CodeInsightUtilBase
;
19 import com
.intellij
.codeInsight
.daemon
.QuickFixBundle
;
20 import com
.intellij
.codeInspection
.IntentionAndQuickFixAction
;
21 import com
.intellij
.openapi
.application
.ApplicationManager
;
22 import com
.intellij
.openapi
.command
.undo
.UndoUtil
;
23 import com
.intellij
.openapi
.diagnostic
.Logger
;
24 import com
.intellij
.openapi
.editor
.Editor
;
25 import com
.intellij
.openapi
.project
.Project
;
26 import com
.intellij
.openapi
.ui
.DialogWrapper
;
27 import com
.intellij
.openapi
.ui
.Messages
;
28 import com
.intellij
.psi
.*;
29 import com
.intellij
.psi
.search
.PsiElementProcessor
;
30 import com
.intellij
.psi
.search
.PsiElementProcessorAdapter
;
31 import com
.intellij
.psi
.search
.searches
.OverridingMethodsSearch
;
32 import com
.intellij
.psi
.util
.PsiFormatUtil
;
33 import com
.intellij
.psi
.util
.PsiUtil
;
34 import com
.intellij
.util
.VisibilityUtil
;
35 import com
.intellij
.util
.IncorrectOperationException
;
36 import org
.jetbrains
.annotations
.NotNull
;
37 import org
.jetbrains
.annotations
.Nullable
;
39 import java
.util
.ArrayList
;
40 import java
.util
.List
;
42 public class ModifierFix
extends IntentionAndQuickFixAction
{
43 private static final Logger LOG
= Logger
.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.ModifierFix");
45 private final PsiModifierList myModifierList
;
46 @Modifier private final String myModifier
;
47 private final boolean myShouldHave
;
48 private final boolean myShowContainingClass
;
49 private PsiVariable myVariable
;
51 public ModifierFix(PsiModifierList modifierList
, @Modifier @NotNull String modifier
, boolean shouldHave
, boolean showContainingClass
) {
52 myModifierList
= modifierList
;
53 myModifier
= modifier
;
54 myShouldHave
= shouldHave
;
55 myShowContainingClass
= showContainingClass
;
57 public ModifierFix(@NotNull PsiModifierListOwner owner
, @Modifier @NotNull String modifier
, boolean shouldHave
, boolean showContainingClass
) {
58 this(owner
.getModifierList(), modifier
, shouldHave
, showContainingClass
);
59 if (owner
instanceof PsiVariable
) {
60 myVariable
= (PsiVariable
)owner
;
65 public String
getName() {
67 PsiElement parent
= myVariable
== null ? myModifierList
.getParent() : myVariable
;
68 if (parent
instanceof PsiClass
) {
69 name
= ((PsiClass
)parent
).getName();
72 int options
= PsiFormatUtil
.SHOW_NAME
| (myShowContainingClass ? PsiFormatUtil
.SHOW_CONTAINING_CLASS
: 0);
73 if (parent
instanceof PsiMethod
) {
74 name
= PsiFormatUtil
.formatMethod((PsiMethod
)parent
, PsiSubstitutor
.EMPTY
, options
, 0);
76 else if (parent
instanceof PsiVariable
) {
77 name
= PsiFormatUtil
.formatVariable((PsiVariable
)parent
, options
, PsiSubstitutor
.EMPTY
);
79 else if (parent
instanceof PsiClassInitializer
) {
80 PsiClass containingClass
= ((PsiClassInitializer
)parent
).getContainingClass();
81 String className
= containingClass
instanceof PsiAnonymousClass
82 ? QuickFixBundle
.message("anonymous.class.presentation", ((PsiAnonymousClass
)containingClass
).getBaseClassType().getPresentableText())
83 : containingClass
.getName();
84 name
= QuickFixBundle
.message("class.initializer.presentation", className
);
88 String modifierText
= VisibilityUtil
.toPresentableText(myModifier
);
90 return QuickFixBundle
.message(myShouldHave ?
"add.modifier.fix" : "remove.modifier.fix", name
, modifierText
);
94 public String
getFamilyName() {
95 return QuickFixBundle
.message("fix.modifiers.family");
98 public boolean isAvailable(@NotNull final Project project
, final Editor editor
, final PsiFile file
) {
99 return myModifierList
!= null &&
100 myModifierList
.isValid() &&
101 myModifierList
.getManager().isInProject(myModifierList
) &&
102 (myVariable
== null || myVariable
.isValid());
105 private void changeModifierList (PsiModifierList modifierList
) {
107 modifierList
.setModifierProperty(myModifier
, myShouldHave
);
109 catch (IncorrectOperationException e
) {
114 public void applyFix(final Project project
, final PsiFile file
, @Nullable final Editor editor
) {
115 if (!CodeInsightUtilBase
.preparePsiElementForWrite(myModifierList
)) return;
116 final List
<PsiModifierList
> modifierLists
= new ArrayList
<PsiModifierList
>();
117 final PsiFile containingFile
= myModifierList
.getContainingFile();
118 final PsiModifierList modifierList
;
119 if (myVariable
!= null && myVariable
.isValid()) {
120 ApplicationManager
.getApplication().runWriteAction(new Runnable() {
123 myVariable
.normalizeDeclaration();
125 catch (IncorrectOperationException e
) {
130 modifierList
= myVariable
.getModifierList();
131 assert modifierList
!= null;
134 modifierList
= myModifierList
;
136 PsiElement owner
= modifierList
.getParent();
137 if (owner
instanceof PsiMethod
) {
138 PsiModifierList copy
= (PsiModifierList
)myModifierList
.copy();
139 changeModifierList(copy
);
140 final int accessLevel
= PsiUtil
.getAccessLevel(copy
);
142 OverridingMethodsSearch
.search((PsiMethod
)owner
, owner
.getResolveScope(), true).forEach(new PsiElementProcessorAdapter
<PsiMethod
>(new PsiElementProcessor
<PsiMethod
>() {
143 public boolean execute(PsiMethod inheritor
) {
144 PsiModifierList list
= inheritor
.getModifierList();
145 if (inheritor
.getManager().isInProject(inheritor
) && PsiUtil
.getAccessLevel(list
) < accessLevel
) {
146 modifierLists
.add(list
);
153 if (!CodeInsightUtilBase
.prepareFileForWrite(containingFile
)) return;
155 if (!modifierLists
.isEmpty()) {
156 if (Messages
.showYesNoDialog(project
,
157 QuickFixBundle
.message("change.inheritors.visibility.warning.text"),
158 QuickFixBundle
.message("change.inheritors.visibility.warning.title"),
159 Messages
.getQuestionIcon()) == DialogWrapper
.OK_EXIT_CODE
) {
160 ApplicationManager
.getApplication().runWriteAction(new Runnable() {
162 if (!CodeInsightUtilBase
.preparePsiElementsForWrite(modifierLists
)) {
166 for (final PsiModifierList modifierList
: modifierLists
) {
167 changeModifierList(modifierList
);
174 ApplicationManager
.getApplication().runWriteAction(new Runnable() {
176 changeModifierList(modifierList
);
177 UndoUtil
.markPsiFileForUndo(containingFile
);
182 public boolean startInWriteAction() {