2 * Copyright 2006 Dave Griffith
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
.global
;
18 import com
.intellij
.analysis
.AnalysisScope
;
19 import com
.intellij
.codeInsight
.daemon
.GroupNames
;
20 import com
.intellij
.codeInspection
.*;
21 import com
.intellij
.codeInspection
.reference
.*;
22 import com
.intellij
.openapi
.diagnostic
.Logger
;
23 import com
.intellij
.openapi
.util
.Key
;
24 import com
.intellij
.psi
.*;
25 import com
.siyeh
.InspectionGadgetsBundle
;
26 import com
.siyeh
.ig
.BaseGlobalInspection
;
27 import com
.siyeh
.ig
.psiutils
.MethodInheritanceUtils
;
28 import org
.jetbrains
.annotations
.NotNull
;
29 import org
.jetbrains
.annotations
.Nullable
;
33 public class MethodReturnAlwaysIgnoredInspection
extends BaseGlobalInspection
{
35 private static final Logger LOG
=
36 Logger
.getInstance("MethodReturnAlwaysIgnoredInspection");
38 private static final Key
<Boolean
> ALWAYS_IGNORED
= Key
.create("ALWAYS_IGNORED_METHOD");
41 public String
getGroupDisplayName() {
42 return GroupNames
.CLASSLAYOUT_GROUP_NAME
;
46 public RefGraphAnnotator
getAnnotator(RefManager refManager
) {
47 return new MethodIgnoredAnnotator();
50 public CommonProblemDescriptor
[] checkElement(RefEntity refEntity
, AnalysisScope scope
,
51 InspectionManager manager
, GlobalInspectionContext globalContext
) {
52 final CommonProblemDescriptor
[] originalProblemDescriptors
=
53 super.checkElement(refEntity
, scope
, manager
, globalContext
);
54 if (!(refEntity
instanceof RefMethod
)) {
57 final RefMethod refMethod
= (RefMethod
) refEntity
;
59 if (methodReturnUsed(refMethod
)) {
60 markSiblings(refMethod
);
61 return originalProblemDescriptors
;
63 if(!(refMethod
.getElement() instanceof PsiMethod
))
65 return originalProblemDescriptors
;
67 final PsiMethod method
= (PsiMethod
) refMethod
.getElement();
69 return originalProblemDescriptors
;
71 if (MethodInheritanceUtils
.inheritsFromLibraryMethod(method
)) {
72 markSiblings(refMethod
);
73 return originalProblemDescriptors
;
76 final ProblemDescriptor descriptor
= manager
.createProblemDescriptor(method
,
77 InspectionGadgetsBundle
.message("method.return.always.ignored.problem.descriptor"),
78 (LocalQuickFix
[]) null,
79 ProblemHighlightType
.GENERIC_ERROR_OR_WARNING
, false);
80 if (originalProblemDescriptors
== null) {
81 return new ProblemDescriptor
[]{descriptor
};
83 final int numDescriptors
= originalProblemDescriptors
.length
;
84 final ProblemDescriptor
[] descriptors
= new ProblemDescriptor
[numDescriptors
+ 1];
85 System
.arraycopy(originalProblemDescriptors
, 0, numDescriptors
+ 1,
87 descriptors
[numDescriptors
] = descriptor
;
92 private void markSiblings(RefMethod refMethod
) {
93 final Set
<RefMethod
> siblingMethods
=
94 MethodInheritanceUtils
.calculateSiblingMethods(refMethod
);
95 for (RefMethod siblingMethod
: siblingMethods
) {
96 siblingMethod
.putUserData(ALWAYS_IGNORED
, false);
100 private static boolean methodReturnUsed(RefMethod refMethod
) {
101 final Boolean alwaysIgnored
= refMethod
.getUserData(ALWAYS_IGNORED
);
102 return alwaysIgnored
== null || !alwaysIgnored
;
105 protected boolean queryExternalUsagesRequests(final RefManager manager
, final GlobalJavaInspectionContext context
,
106 final ProblemDescriptionsProcessor descriptionsProcessor
) {
107 manager
.iterate(new RefJavaVisitor() {
108 @Override public void visitMethod(final RefMethod refMethod
) {
109 if (methodReturnUsed(refMethod
)) {
112 final GlobalJavaInspectionContext
.UsagesProcessor usagesProcessor
=
113 new GlobalJavaInspectionContext
.UsagesProcessor() {
114 public boolean process(PsiReference psiReference
) {
115 final PsiElement psiReferenceExpression
= psiReference
.getElement();
116 final PsiElement parent
= psiReferenceExpression
.getParent();
117 if (parent
instanceof PsiMethodCallExpression
&&
118 !isIgnoredMethodCall((PsiCallExpression
) parent
)) {
119 descriptionsProcessor
.ignoreElement(refMethod
);
124 context
.enqueueMethodUsagesProcessor(refMethod
, usagesProcessor
);
130 private static boolean isIgnoredMethodCall
133 final PsiElement parent
= methodExpression
.getParent();
134 return parent
instanceof PsiExpressionStatement
;
137 private static class MethodIgnoredAnnotator
extends RefGraphAnnotator
{
138 public void onInitialize(RefElement refElement
) {
139 super.onInitialize(refElement
);
140 if (!(refElement
instanceof RefMethod
)) {
143 final RefMethod refMethod
= (RefMethod
) refElement
;
144 final PsiElement element
= refElement
.getElement();
145 if (!(element
instanceof PsiMethod
)) {
148 final PsiMethod method
= (PsiMethod
) element
;
149 final PsiType returnType
= method
.getReturnType();
150 if (PsiType
.VOID
.equals(returnType
)) {
153 LOG
.info("onInitialize:" + refMethod
.getName());
154 refElement
.putUserData(ALWAYS_IGNORED
, true);
157 public void onMarkReferenced(RefElement refWhat
,
159 boolean referencedFromClassInitializer
) {
160 super.onMarkReferenced(refWhat
, refFrom
, referencedFromClassInitializer
);
161 if (!(refWhat
instanceof RefMethod
)) {
165 final RefMethod refMethod
= (RefMethod
) refWhat
;
167 if (methodReturnUsed(refMethod
)) {
170 final PsiElement psiElement
= refMethod
.getElement();
171 if (!(psiElement
instanceof PsiMethod
)) {
174 final PsiMethod psiMethod
= (PsiMethod
) psiElement
;
175 LOG
.info("onMarkReferenced:" + refMethod
.getName());
177 final PsiElement element
= refFrom
.getElement();
178 element
.accept(new JavaRecursiveElementVisitor() {
179 @Override public void visitMethodCallExpression(PsiMethodCallExpression call
) {
180 if (methodReturnUsed(refMethod
)) {
183 super.visitMethodCallExpression(call
);
184 if (isIgnoredMethodCall(call
)) {
187 final PsiReferenceExpression methodExpression
=
188 call
.getMethodExpression();
189 if (methodExpression
.isReferenceTo(psiMethod
)) {
190 refMethod
.putUserData(ALWAYS_IGNORED
, false);
194 @Override public void visitNewExpression(PsiNewExpression call
) {
195 if (methodReturnUsed(refMethod
)) {
198 super.visitNewExpression(call
);
199 if (isIgnoredMethodCall(call
)) {
203 final PsiMethod referedMethod
= call
.resolveMethod();
204 if (psiMethod
.equals(referedMethod
)) {
205 refMethod
.putUserData(ALWAYS_IGNORED
, false);