EditorConfig documentation test
[idea/community.git] / java / java-impl / src / com / intellij / codeInsight / daemon / impl / quickfix / DefaultQuickFixProvider.java
1 // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package com.intellij.codeInsight.daemon.impl.quickfix;
3
4 import com.intellij.codeInsight.daemon.QuickFixActionRegistrar;
5 import com.intellij.codeInsight.daemon.impl.analysis.HighlightMethodUtil;
6 import com.intellij.codeInsight.intention.IntentionAction;
7 import com.intellij.codeInsight.intention.QuickFixFactory;
8 import com.intellij.codeInsight.intention.impl.PriorityIntentionActionWrapper;
9 import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider;
10 import com.intellij.lang.java.request.CreateFieldFromUsage;
11 import com.intellij.openapi.util.TextRange;
12 import com.intellij.openapi.util.text.StringUtil;
13 import com.intellij.psi.*;
14 import com.intellij.psi.codeStyle.JavaCodeStyleManager;
15 import com.intellij.psi.codeStyle.VariableKind;
16 import com.intellij.psi.util.PsiTreeUtil;
17 import com.intellij.psi.util.PsiUtil;
18 import org.jetbrains.annotations.NotNull;
19 import org.jetbrains.annotations.Nullable;
20
21 import java.util.ArrayList;
22 import java.util.Collection;
23
24 public class DefaultQuickFixProvider extends UnresolvedReferenceQuickFixProvider<PsiJavaCodeReferenceElement> {
25   @Override
26   public void registerFixes(@NotNull PsiJavaCodeReferenceElement ref, @NotNull QuickFixActionRegistrar registrar) {
27     PsiFile containingFile = ref.getContainingFile();
28     if (containingFile instanceof PsiJavaCodeReferenceCodeFragment &&
29         !((PsiJavaCodeReferenceCodeFragment)containingFile).isClassesAccepted()) {
30       return;
31     }
32     if (PsiUtil.isModuleFile(containingFile)) {
33       OrderEntryFix.registerFixes(registrar, ref);
34       registrar.register(new CreateServiceImplementationClassFix(ref));
35       registrar.register(new CreateServiceInterfaceOrClassFix(ref));
36       return;
37     }
38
39     QuickFixFactory quickFixFactory = QuickFixFactory.getInstance();
40     registrar.register(new ImportClassFix(ref));
41     registrar.register(new StaticImportConstantFix(containingFile, ref));
42     registrar.register(new QualifyStaticConstantFix(containingFile, ref));
43     registrar.register(quickFixFactory.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(new RenameWrongRefFix(refExpr));
54       PsiExpression qualifier = ((PsiReferenceExpression)ref).getQualifierExpression();
55       if (qualifier == null) {
56         registrar.register(fixRange, new BringVariableIntoScopeFix(refExpr), null);
57       }
58       else {
59         AddTypeCastFix.registerFix(registrar, qualifier, ref, fixRange);
60       }
61
62       for (IntentionAction action : createVariableActions(refExpr)) {
63         registrar.register(fixRange, action, null);
64       }
65     }
66
67     registrar.register(new CreateClassFromUsageFix(ref, CreateClassKind.INTERFACE));
68     if (PsiUtil.isLanguageLevel5OrHigher(ref)) {
69       registrar.register(new CreateClassFromUsageFix(ref, CreateClassKind.ENUM));
70       registrar.register(new CreateClassFromUsageFix(ref, CreateClassKind.ANNOTATION));
71       registrar.register(new CreateTypeParameterFromUsageFix(ref));
72     }
73
74     PsiElement parent = PsiTreeUtil.getParentOfType(ref, PsiNewExpression.class, PsiMethod.class);
75     PsiExpressionList expressionList = PsiTreeUtil.getParentOfType(ref, PsiExpressionList.class);
76     if (parent instanceof PsiNewExpression &&
77         !(ref.getParent() instanceof PsiTypeElement) &&
78         (expressionList == null || !PsiTreeUtil.isAncestor(parent, expressionList, false))) {
79       registrar.register(new CreateClassFromNewFix((PsiNewExpression)parent));
80       registrar.register(new CreateInnerClassFromNewFix((PsiNewExpression)parent));
81     }
82     else {
83       registrar.register(new CreateClassFromUsageFix(ref, CreateClassKind.CLASS));
84       registrar.register(new CreateInnerClassFromUsageFix(ref, CreateClassKind.CLASS));
85     }
86
87     SurroundWithQuotesAnnotationParameterValueFix.register(registrar, ref);
88   }
89
90   @NotNull
91   private static Collection<IntentionAction> createVariableActions(@NotNull PsiReferenceExpression refExpr) {
92     final Collection<IntentionAction> result = new ArrayList<>(CreateFieldFromUsage.generateActions(refExpr));
93     if (!refExpr.isQualified()) {
94       final VariableKind kind = getKind(refExpr);
95       IntentionAction createLocalFix = new CreateLocalFromUsageFix(refExpr);
96       result.add(kind == VariableKind.LOCAL_VARIABLE ? PriorityIntentionActionWrapper.highPriority(createLocalFix) : createLocalFix);
97       IntentionAction createParameterFix = new CreateParameterFromUsageFix(refExpr);
98       result.add(kind == VariableKind.PARAMETER ? PriorityIntentionActionWrapper.highPriority(createParameterFix) : createParameterFix);
99     }
100     return result;
101   }
102
103   @Nullable
104   private static VariableKind getKind(@NotNull PsiReferenceExpression refExpr) {
105     final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(refExpr.getProject());
106     final String reference = refExpr.getText();
107
108     if (StringUtil.isUpperCase(reference)) {
109       return VariableKind.STATIC_FINAL_FIELD;
110     }
111
112     for (VariableKind kind : VariableKind.values()) {
113       final String prefix = styleManager.getPrefixByVariableKind(kind);
114       final String suffix = styleManager.getSuffixByVariableKind(kind);
115
116       if (prefix.isEmpty() && suffix.isEmpty()) {
117         continue;
118       }
119
120       if (reference.startsWith(prefix) && reference.endsWith(suffix)) {
121         return kind;
122       }
123     }
124
125     if (StringUtil.isCapitalized(reference)) {
126       return null;
127     }
128
129     return VariableKind.LOCAL_VARIABLE;
130   }
131
132   @Override
133   @NotNull
134   public Class<PsiJavaCodeReferenceElement> getReferenceClass() {
135     return PsiJavaCodeReferenceElement.class;
136   }
137 }