IDEADEV-40452
[fedora-idea.git] / plugins / InspectionGadgets / src / com / siyeh / ig / threading / AwaitWithoutCorrespondingSignalInspection.java
blob487143581862bd8c3a8e1438c9177fd04b19b4ac
1 /*
2 * Copyright 2003-2007 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.threading;
18 import com.intellij.psi.*;
19 import com.intellij.psi.util.PsiTreeUtil;
20 import com.siyeh.InspectionGadgetsBundle;
21 import com.siyeh.ig.BaseInspection;
22 import com.siyeh.ig.BaseInspectionVisitor;
23 import org.jetbrains.annotations.NotNull;
25 public class AwaitWithoutCorrespondingSignalInspection extends BaseInspection {
27 @NotNull
28 public String getDisplayName() {
29 return InspectionGadgetsBundle.message(
30 "await.without.corresponding.signal.display.name");
33 @NotNull
34 protected String buildErrorString(Object... infos) {
35 return InspectionGadgetsBundle.message(
36 "await.without.corresponding.signal.problem.descriptor");
38 public BaseInspectionVisitor buildVisitor() {
39 return new AwaitWithoutCorrespondingSignalVisitor();
42 private static class AwaitWithoutCorrespondingSignalVisitor
43 extends BaseInspectionVisitor {
45 @Override public void visitMethodCallExpression(
46 @NotNull PsiMethodCallExpression expression) {
47 super.visitMethodCallExpression(expression);
48 if (!ThreadingUtils.isAwaitCall(expression)) {
49 return;
52 final PsiReferenceExpression methodExpression =
53 expression.getMethodExpression();
54 final PsiExpression qualifier =
55 methodExpression.getQualifierExpression();
56 if (!(qualifier instanceof PsiReferenceExpression)) {
57 return;
59 final PsiElement referent = ((PsiReference) qualifier).resolve();
60 if (!(referent instanceof PsiField)) {
61 return;
63 final PsiField field = (PsiField) referent;
64 final PsiClass fieldClass = field.getContainingClass();
65 if (fieldClass == null) {
66 return;
68 if (!PsiTreeUtil.isAncestor(fieldClass, expression, true)) {
69 return;
71 if (containsSignalCall(fieldClass, field)) {
72 return;
74 registerMethodCallError(expression);
77 private static boolean containsSignalCall(PsiClass fieldClass,
78 PsiField field) {
79 final ContainsSignalVisitor visitor =
80 new ContainsSignalVisitor(field);
81 fieldClass.accept(visitor);
82 return visitor.containsSignal();
86 private static class ContainsSignalVisitor
87 extends JavaRecursiveElementVisitor {
89 private final PsiField target;
90 private boolean containsSignal = false;
92 ContainsSignalVisitor(PsiField target) {
93 super();
94 this.target = target;
97 @Override public void visitElement(PsiElement element) {
98 if (containsSignal) {
99 return;
101 super.visitElement(element);
104 @Override public void visitMethodCallExpression(
105 PsiMethodCallExpression expression) {
106 super.visitMethodCallExpression(expression);
107 if (!ThreadingUtils.isSignalOrSignalAllCall(expression)) {
108 return;
110 final PsiReferenceExpression methodExpression =
111 expression.getMethodExpression();
112 final PsiExpression qualifier =
113 methodExpression.getQualifierExpression();
114 if (qualifier == null) {
115 return;
117 if (!(qualifier instanceof PsiReferenceExpression)) {
118 return;
120 final PsiElement referent = ((PsiReference) qualifier).resolve();
121 if (referent == null) {
122 return;
124 if (!target.equals(referent)) {
125 return;
127 containsSignal = true;
130 public boolean containsSignal() {
131 return containsSignal;