Inspections - pass onTheFly into ProblemDescriptors & use it to create LAZY refs...
[fedora-idea.git] / plugins / InspectionGadgets / src / com / siyeh / ig / global / MethodReturnAlwaysIgnoredInspection.java
blobf0b0832d85f556043aaec36f243f1350ddc8dfd5
1 /*
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;
31 import java.util.Set;
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");
40 @NotNull
41 public String getGroupDisplayName() {
42 return GroupNames.CLASSLAYOUT_GROUP_NAME;
45 @Nullable
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)) {
55 return null;
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();
68 if (method == null) {
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};
82 } else {
83 final int numDescriptors = originalProblemDescriptors.length;
84 final ProblemDescriptor[] descriptors = new ProblemDescriptor[numDescriptors + 1];
85 System.arraycopy(originalProblemDescriptors, 0, numDescriptors + 1,
86 0, numDescriptors);
87 descriptors[numDescriptors] = descriptor;
88 return descriptors;
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)) {
110 return;
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);
121 return false;
124 context.enqueueMethodUsagesProcessor(refMethod, usagesProcessor);
127 return false;
130 private static boolean isIgnoredMethodCall
131 (PsiCallExpression
132 methodExpression) {
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)) {
141 return;
143 final RefMethod refMethod = (RefMethod) refElement;
144 final PsiElement element = refElement.getElement();
145 if (!(element instanceof PsiMethod)) {
146 return;
148 final PsiMethod method = (PsiMethod) element;
149 final PsiType returnType = method.getReturnType();
150 if (PsiType.VOID.equals(returnType)) {
151 return;
153 LOG.info("onInitialize:" + refMethod.getName());
154 refElement.putUserData(ALWAYS_IGNORED, true);
157 public void onMarkReferenced(RefElement refWhat,
158 RefElement refFrom,
159 boolean referencedFromClassInitializer) {
160 super.onMarkReferenced(refWhat, refFrom, referencedFromClassInitializer);
161 if (!(refWhat instanceof RefMethod)) {
162 return;
165 final RefMethod refMethod = (RefMethod) refWhat;
167 if (methodReturnUsed(refMethod)) {
168 return;
170 final PsiElement psiElement = refMethod.getElement();
171 if (!(psiElement instanceof PsiMethod)) {
172 return;
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)) {
181 return;
183 super.visitMethodCallExpression(call);
184 if (isIgnoredMethodCall(call)) {
185 return;
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)) {
196 return;
198 super.visitNewExpression(call);
199 if (isIgnoredMethodCall(call)) {
200 return;
203 final PsiMethod referedMethod = call.resolveMethod();
204 if (psiMethod.equals(referedMethod)) {
205 refMethod.putUserData(ALWAYS_IGNORED, false);