a2fbb5359fe4da1094c66ad83c7669f03747a1d1
[idea/community.git] / java / java-impl / src / com / intellij / codeInsight / daemon / impl / quickfix / DefaultQuickFixProvider.java
1 /*
2  * Copyright 2000-2013 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package com.intellij.codeInsight.daemon.impl.quickfix;
17
18 import com.intellij.codeInsight.daemon.QuickFixActionRegistrar;
19 import com.intellij.codeInsight.daemon.impl.analysis.HighlightMethodUtil;
20 import com.intellij.codeInsight.intention.IntentionAction;
21 import com.intellij.codeInsight.intention.QuickFixFactory;
22 import com.intellij.codeInsight.intention.impl.PriorityIntentionActionWrapper;
23 import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider;
24 import com.intellij.openapi.util.TextRange;
25 import com.intellij.openapi.util.text.StringUtil;
26 import com.intellij.psi.*;
27 import com.intellij.psi.codeStyle.JavaCodeStyleManager;
28 import com.intellij.psi.codeStyle.VariableKind;
29 import com.intellij.psi.util.PsiTreeUtil;
30 import com.intellij.psi.util.PsiUtil;
31 import org.jetbrains.annotations.NotNull;
32 import org.jetbrains.annotations.Nullable;
33
34 import java.util.EnumMap;
35 import java.util.Map;
36
37 public class DefaultQuickFixProvider extends UnresolvedReferenceQuickFixProvider<PsiJavaCodeReferenceElement> {
38   @Override
39   public void registerFixes(@NotNull PsiJavaCodeReferenceElement ref, @NotNull QuickFixActionRegistrar registrar) {
40     QuickFixFactory factory = QuickFixFactory.getInstance();
41     registrar.register(new ImportClassFix(ref));
42     registrar.register(new StaticImportConstantFix(ref));
43     registrar.register(factory.createSetupJDKFix());
44
45     OrderEntryFix.registerFixes(registrar, ref);
46
47     MoveClassToModuleFix.registerFixes(registrar, ref);
48
49     if (ref instanceof PsiReferenceExpression) {
50       TextRange fixRange = HighlightMethodUtil.getFixRange(ref);
51       PsiReferenceExpression refExpr = (PsiReferenceExpression)ref;
52
53       registrar.register(fixRange, new CreateEnumConstantFromUsageFix(refExpr), null);
54       registrar.register(new RenameWrongRefFix(refExpr));
55
56       if (!ref.isQualified()) {
57         registrar.register(fixRange, new BringVariableIntoScopeFix(refExpr), null);
58       }
59
60       registerPriorityActions(registrar, fixRange, refExpr);
61     }
62
63     registrar.register(new CreateClassFromUsageFix(ref, CreateClassKind.INTERFACE));
64     if (PsiUtil.isLanguageLevel5OrHigher(ref)) {
65       registrar.register(new CreateClassFromUsageFix(ref, CreateClassKind.ENUM));
66       registrar.register(new CreateClassFromUsageFix(ref, CreateClassKind.ANNOTATION));
67     }
68
69     PsiElement parent = PsiTreeUtil.getParentOfType(ref, PsiNewExpression.class, PsiMethod.class);
70     PsiExpressionList expressionList = PsiTreeUtil.getParentOfType(ref, PsiExpressionList.class);
71     if (parent instanceof PsiNewExpression &&
72         !(ref.getParent() instanceof PsiTypeElement) &&
73         (expressionList == null || !PsiTreeUtil.isAncestor(parent, expressionList, false))) {
74       registrar.register(new CreateClassFromNewFix((PsiNewExpression)parent));
75       registrar.register(new CreateInnerClassFromNewFix((PsiNewExpression)parent));
76     }
77     else {
78       registrar.register(new CreateClassFromUsageFix(ref, CreateClassKind.CLASS));
79       registrar.register(new CreateInnerClassFromUsageFix(ref, CreateClassKind.CLASS));
80     }
81   }
82
83   private static void registerPriorityActions(@NotNull QuickFixActionRegistrar registrar,
84                                               @NotNull TextRange fixRange,
85                                               @NotNull PsiReferenceExpression refExpr) {
86     final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(refExpr.getProject());
87
88     final Map<VariableKind, IntentionAction> map = new EnumMap<>(VariableKind.class);
89     map.put(VariableKind.FIELD, new CreateFieldFromUsageFix(refExpr));
90     map.put(VariableKind.STATIC_FINAL_FIELD, new CreateConstantFieldFromUsageFix(refExpr));
91     if (!refExpr.isQualified()) {
92       map.put(VariableKind.LOCAL_VARIABLE, new CreateLocalFromUsageFix(refExpr));
93       map.put(VariableKind.PARAMETER, new CreateParameterFromUsageFix(refExpr));
94     }
95
96     final VariableKind kind = getKind(styleManager, refExpr);
97     if (map.containsKey(kind)) {
98       map.put(kind, PriorityIntentionActionWrapper.highPriority(map.get(kind)));
99     }
100
101     for (IntentionAction action : map.values()) {
102       registrar.register(fixRange, action, null);
103     }
104   }
105
106   @Nullable
107   private static VariableKind getKind(@NotNull JavaCodeStyleManager styleManager, @NotNull PsiReferenceExpression refExpr) {
108     final String reference = refExpr.getText();
109
110     if (reference.toUpperCase().equals(reference)){
111       return VariableKind.STATIC_FINAL_FIELD;
112     }
113
114     for (VariableKind kind : VariableKind.values()) {
115       final String prefix = styleManager.getPrefixByVariableKind(kind);
116       final String suffix = styleManager.getSuffixByVariableKind(kind);
117
118       if (prefix.isEmpty() && suffix.isEmpty()) {
119         continue;
120       }
121
122       if (reference.startsWith(prefix) && reference.endsWith(suffix)) {
123         return kind;
124       }
125     }
126
127     if (StringUtil.isCapitalized(reference)) {
128       return null;
129     }
130
131     return VariableKind.LOCAL_VARIABLE;
132   }
133
134   @Override
135   @NotNull
136   public Class<PsiJavaCodeReferenceElement> getReferenceClass() {
137     return PsiJavaCodeReferenceElement.class;
138   }
139 }