2 * Copyright 2003-2009 Dave Griffith, Bas Leijdekkers
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
.siyeh
.ig
.style
;
18 import com
.intellij
.codeInspection
.ProblemDescriptor
;
19 import com
.intellij
.openapi
.project
.Project
;
20 import com
.intellij
.psi
.*;
21 import com
.intellij
.psi
.util
.PsiTreeUtil
;
22 import com
.intellij
.util
.IncorrectOperationException
;
23 import com
.siyeh
.InspectionGadgetsBundle
;
24 import com
.siyeh
.ig
.BaseInspection
;
25 import com
.siyeh
.ig
.BaseInspectionVisitor
;
26 import com
.siyeh
.ig
.InspectionGadgetsFix
;
27 import com
.siyeh
.ig
.psiutils
.ClassUtils
;
28 import com
.siyeh
.ig
.ui
.MultipleCheckboxOptionsPanel
;
29 import org
.jetbrains
.annotations
.NotNull
;
33 public class UnnecessarilyQualifiedStaticUsageInspection
34 extends BaseInspection
{
36 /** @noinspection PublicField*/
37 public boolean m_ignoreStaticFieldAccesses
= false;
39 /** @noinspection PublicField*/
40 public boolean m_ignoreStaticMethodCalls
= false;
42 /** @noinspection PublicField*/
43 public boolean m_ignoreStaticAccessFromStaticContext
= false;
47 public String
getDisplayName() {
48 return InspectionGadgetsBundle
.message(
49 "unnecessarily.qualified.static.usage.display.name");
54 public String
buildErrorString(Object
... infos
) {
55 final PsiJavaCodeReferenceElement element
=
56 (PsiJavaCodeReferenceElement
)infos
[0];
57 final PsiElement parent
= element
.getParent();
58 if (parent
instanceof PsiMethodCallExpression
) {
59 return InspectionGadgetsBundle
.message(
60 "unnecessarily.qualified.static.usage.problem.descriptor");
62 return InspectionGadgetsBundle
.message(
63 "unnecessarily.qualified.static.usage.problem.descriptor1");
68 public JComponent
createOptionsPanel() {
69 final MultipleCheckboxOptionsPanel optionsPanel
=
70 new MultipleCheckboxOptionsPanel(this);
71 optionsPanel
.addCheckbox(InspectionGadgetsBundle
.message(
72 "unnecessarily.qualified.static.usage.ignore.field.option"),
73 "m_ignoreStaticFieldAccesses");
74 optionsPanel
.addCheckbox(InspectionGadgetsBundle
.message(
75 "unnecessarily.qualified.static.usage.ignore.method.option"),
76 "m_ignoreStaticMethodCalls");
77 optionsPanel
.addCheckbox(InspectionGadgetsBundle
.message(
78 "only.report.qualified.static.usages.option"),
79 "m_ignoreStaticAccessFromStaticContext");
84 public InspectionGadgetsFix
buildFix(Object
... infos
) {
85 return new UnnecessarilyQualifiedStaticUsageFix();
88 private static class UnnecessarilyQualifiedStaticUsageFix
89 extends InspectionGadgetsFix
{
92 public String
getName() {
93 return InspectionGadgetsBundle
.message(
94 "unnecessary.qualifier.for.this.remove.quickfix");
98 public void doFix(Project project
, ProblemDescriptor descriptor
)
99 throws IncorrectOperationException
{
100 final PsiElement element
= descriptor
.getPsiElement();
101 if (element
instanceof PsiJavaCodeReferenceElement
) {
102 final PsiJavaCodeReferenceElement reference
=
103 (PsiJavaCodeReferenceElement
) element
;
104 final PsiElement qualifier
= reference
.getQualifier();
105 if (qualifier
== null) {
114 public BaseInspectionVisitor
buildVisitor() {
115 return new UnnecessarilyQualifiedStaticUsageVisitor();
118 private class UnnecessarilyQualifiedStaticUsageVisitor
119 extends BaseInspectionVisitor
{
121 @Override public void visitReferenceElement(
122 PsiJavaCodeReferenceElement reference
) {
123 super.visitReferenceElement(reference
);
124 if (!isUnnecessarilyQualifiedAccess(reference
)) {
127 registerError(reference
, reference
);
130 @Override public void visitReferenceExpression(
131 PsiReferenceExpression expression
) {
132 visitReferenceElement(expression
);
135 private boolean isUnnecessarilyQualifiedAccess(
136 @NotNull PsiJavaCodeReferenceElement referenceElement
) {
137 final PsiElement parent
= referenceElement
.getParent();
138 if (parent
instanceof PsiJavaCodeReferenceElement
||
139 parent
instanceof PsiImportStatementBase
) {
142 final PsiElement qualifierElement
=
143 referenceElement
.getQualifier();
144 if(!(qualifierElement
instanceof PsiJavaCodeReferenceElement
)){
147 final PsiElement target
= referenceElement
.resolve();
148 if ((!(target
instanceof PsiField
) || m_ignoreStaticFieldAccesses
) &&
149 (!(target
instanceof PsiMethod
) || m_ignoreStaticMethodCalls
) &&
150 !(target
instanceof PsiClass
)) {
153 if (m_ignoreStaticAccessFromStaticContext
) {
154 final PsiMember containingMember
=
155 PsiTreeUtil
.getParentOfType(referenceElement
,
157 if (containingMember
!= null &&
158 !containingMember
.hasModifierProperty(
159 PsiModifier
.STATIC
)) {
163 final String referenceName
= referenceElement
.getReferenceName();
164 if(referenceName
== null) {
167 final PsiReference reference
= (PsiReference
)qualifierElement
;
168 final PsiElement resolvedQualifier
= reference
.resolve();
169 if (!(resolvedQualifier
instanceof PsiClass
)) {
172 final PsiClass qualifyingClass
= (PsiClass
)resolvedQualifier
;
173 final Project project
= referenceElement
.getProject();
174 final JavaPsiFacade manager
= JavaPsiFacade
.getInstance(project
);
175 final PsiResolveHelper resolveHelper
= manager
.getResolveHelper();
176 final PsiMember member
= (PsiMember
) target
;
177 final PsiClass containingClass
;
178 if (target
instanceof PsiField
) {
179 final PsiVariable variable
=
180 resolveHelper
.resolveReferencedVariable(referenceName
,
182 if (variable
== null || !variable
.equals(member
)) {
185 final PsiMember memberVariable
= (PsiMember
)variable
;
186 containingClass
= memberVariable
.getContainingClass();
187 } else if (target
instanceof PsiClass
) {
188 final PsiClass aClass
=
189 resolveHelper
.resolveReferencedClass(referenceName
,
191 if (aClass
== null || !aClass
.equals(member
)) {
194 containingClass
= aClass
.getContainingClass();
196 return isMethodAccessibleWithoutQualifier(referenceElement
,
199 return resolvedQualifier
.equals(containingClass
);
202 private boolean isMethodAccessibleWithoutQualifier(
203 PsiJavaCodeReferenceElement referenceElement
,
204 PsiClass qualifyingClass
) {
205 final String referenceName
= referenceElement
.getReferenceName();
206 if (referenceName
== null) {
209 PsiClass containingClass
=
210 ClassUtils
.getContainingClass(referenceElement
);
211 while (containingClass
!= null) {
212 final PsiMethod
[] methods
=
213 containingClass
.findMethodsByName(referenceName
,
215 for(final PsiMethod method
: methods
) {
216 final String name
= method
.getName();
217 if(referenceName
.equals(name
)) {
218 return containingClass
.equals(qualifyingClass
);
222 ClassUtils
.getContainingClass(containingClass
);