From 6d2e193373d660dbd96534c66eab181c5efd6b51 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Mon, 11 May 2015 11:09:49 +0200 Subject: [PATCH] IDEA-111282 (False positive on "while loop spins on field", where wait() is used) --- .../WhileLoopSpinsOnFieldInspection.java | 20 +++++++++++++++++-- .../WhileLoopSpinsOnField.java | 14 +++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/WhileLoopSpinsOnFieldInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/WhileLoopSpinsOnFieldInspection.java index cbd9b479e970..b42eae42c1e7 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/WhileLoopSpinsOnFieldInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/WhileLoopSpinsOnFieldInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2015 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -74,12 +74,28 @@ public class WhileLoopSpinsOnFieldInspection extends BaseInspection { if (field == null) { return; } - if (body != null && VariableAccessUtils.variableIsAssigned(field, body)) { + if (body != null && (VariableAccessUtils.variableIsAssigned(field, body) || + containsWaitCall(body))) { return; } registerStatementError(statement); } + private boolean containsWaitCall(PsiElement element) { + final boolean[] result = new boolean[1]; + element.accept(new JavaRecursiveElementWalkingVisitor() { + @Override + public void visitMethodCallExpression(PsiMethodCallExpression expression) { + super.visitMethodCallExpression(expression); + if (ThreadingUtils.isWaitCall(expression)) { + result[0] = true; + stopWalking(); + } + } + }); + return result[0]; + } + @Nullable private PsiField getFieldIfSimpleFieldComparison(PsiExpression condition) { condition = PsiUtil.deparenthesizeExpression(condition); diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/threading/while_loop_spins_on_field/WhileLoopSpinsOnField.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/threading/while_loop_spins_on_field/WhileLoopSpinsOnField.java index cbf00d8bef9f..23609319e27a 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/threading/while_loop_spins_on_field/WhileLoopSpinsOnField.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/threading/while_loop_spins_on_field/WhileLoopSpinsOnField.java @@ -69,4 +69,18 @@ class WhileLoopSpinsOnField2 } } } +class WhileLoopSpinsOnFieldFalsePosDemo { + private boolean field = false; + public synchronized void setAndNotify() { + field = true; + this.notifyAll(); + } + + public synchronized void waitForStuff() throws InterruptedException { + // IDEA incorrectly reports "'while' loop spins on field" here: + while (!field) { // <— this line + this.wait(); // this has the effect of synchronizing the field correctly + } + } +}