IDEA-309523 add more test, fix inspection message, fix hierarchical annotation check

GitOrigin-RevId: 5bf28e687272eb39f9207989f9ef04a26acb2f27
This commit is contained in:
Elena Lyulina
2023-05-29 20:33:24 +00:00
committed by intellij-monorepo-bot
parent d481c0d67e
commit 04b18c8a36
50 changed files with 246 additions and 83 deletions
@@ -654,7 +654,7 @@ inspection.extension.registered.as.service.message=A class must not be registere
inspection.extension.registered.as.component.message=A class must not be registered as both an extension and a component
inspection.cancellation.check.in.loops.display.name=Cancellation check in loops
inspection.cancellation.check.in.loops.message=Cancellation check ''{0}'' should be placed in the first line
inspection.cancellation.check.in.loops.message=Cancellation check ''{0}'' should be the first statement in a loop body
inspection.insert.cancellation.check.fix.message=Insert cancellation check
inspections.application.service.as.static.final.field.display.name=Application service assigned to a static final field/property
@@ -1,6 +1,7 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.idea.devkit.inspections
import com.intellij.codeInsight.AnnotationUtil
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.PsiElementVisitor
import com.intellij.uast.UastHintedVisitorAdapter
@@ -77,8 +78,7 @@ class CancellationCheckInLoopsInspection : DevKitUastInspectionBase() {
*/
private fun shouldBeRunOn(uElement: UElement): Boolean {
val containingMethod = uElement.getParentOfType<UMethod>() ?: return false
val superMethods = containingMethod.javaPsi.findSuperMethods()
return superMethods.plus(containingMethod).any { it.hasAnnotation(RequiresReadLock::class.java.canonicalName) }
return AnnotationUtil.isAnnotated(containingMethod.javaPsi, RequiresReadLock::class.java.canonicalName, AnnotationUtil.CHECK_HIERARCHY)
}
private val ULoopExpression.bodyExpressions: List<UExpression>
@@ -0,0 +1,37 @@
package inspections.cancellationCheckInLoops;
import com.intellij.util.concurrency.annotations.RequiresReadLock;
import com.intellij.openapi.progress.ProgressManager;
import static inspections.cancellationCheckInLoops.Foo.doSomething;
class Clazz {
@RequiresReadLock
public static void foo() {
String[] items = {""};
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (String item : items) {
doSomething();
ProgressManager.checkCanceled();
}
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (int i = 0; i < 5; i++) {
doSomething();
ProgressManager.checkCanceled();
}
int i = 0;
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">while</warning> (i < 5) {
doSomething();
ProgressManager.checkCanceled();
i++;
}
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">do</warning> {
doSomething();
i++;
ProgressManager.checkCanceled();
} while (i < 10);
}
}
@@ -13,9 +13,9 @@ class Clazz {
int j = 0;
do {
// nested loops with something in between
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">do</warning> {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">do</warning> {
doSomething();
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">do</warning> {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">do</warning> {
doSomething();
i++;
} while (i < 10);
@@ -23,20 +23,20 @@ class Clazz {
} while (i < 5);
// nested loops with a block in between
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">do</warning> {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">do</warning> {
if (i != 3) {
//empty loop
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">do</warning> {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">do</warning> {
} while (j > 5);
}
i++;
} while (i < 15);
// single-line loop
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">do</warning> System.out.println(i); while (i < 20);
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">do</warning> System.out.println(i); while (i < 20);
// no body loop
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">do</warning>; while(i < 0);
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">do</warning>; while(i < 0);
i++;
} while (i < 100);
@@ -14,27 +14,27 @@ class Clazz {
for (String item : items) {
// nested loops with something in between
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for</warning> (String item2 : items) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (String item2 : items) {
doSomething();
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for</warning> (String item3 : items) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (String item3 : items) {
doSomething();
}
}
// nested loops with a block in between
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for</warning> (String item4 : items) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (String item4 : items) {
if (item != "") {
//empty loop
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for</warning> (String item5 : items) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (String item5 : items) {
}
}
}
// single-line loop
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for</warning> (String item6: items) System.out.println(item);
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (String item6: items) System.out.println(item);
// no body loop
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for</warning>(String item5 : items);
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning>(String item5 : items);
}
}
}
@@ -12,27 +12,27 @@ class Clazz {
for (int i = 0; i < 5; i++) {
// nested loops with something in between
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for</warning> (int j = 0; j < 5; j++) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (int j = 0; j < 5; j++) {
doSomething();
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for</warning> (int k = 0; k < 5; k++) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (int k = 0; k < 5; k++) {
doSomething();
}
}
// nested loops with a block in between
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for</warning> (int j = 0; j < 5; j++) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (int j = 0; j < 5; j++) {
if (j != 3) {
//empty loop
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for</warning> (int k = 0; k < 5; k++) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (int k = 0; k < 5; k++) {
}
}
}
// single-line loop
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for</warning> (int j = 0; j < 5; j++) System.out.println(j);
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (int j = 0; j < 5; j++) System.out.println(j);
// no body loop
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for</warning> (int y = 0; y < 10; y++);
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (int y = 0; y < 10; y++);
}
}
}
@@ -15,7 +15,7 @@ class Clazz {
while (j < 100) {
for (int i = 0; i < 5; i++) {
for (String item : items) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">do</warning> {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">do</warning> {
doSomething();
j++;
} while (j < 5);
@@ -25,7 +25,7 @@ class Clazz {
}
// single line nested loops
for (int i = 0; i < 5; i++) <warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for</warning> (String item : items) {
for (int i = 0; i < 5; i++) <warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (String item : items) {
doSomething();
}
}
@@ -15,7 +15,7 @@ class Bar {
@RequiresReadLock
public void barReadLock() {
String[] items = {""};
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for</warning> (String item : items) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (String item : items) {
doSomething();
}
}
@@ -0,0 +1,25 @@
package inspections.cancellationCheckInLoops;
import com.intellij.util.concurrency.annotations.RequiresReadLock;
import static inspections.cancellationCheckInLoops.Foo.doSomething;
abstract class Bar {
@RequiresReadLock
public abstract void bar();
}
class BarImpl extends Bar {
@Override
public void bar() {
String[] items = {""};
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (String item : items) {
doSomething();
}
}
}
@@ -13,9 +13,9 @@ class Clazz {
int j = 0;
while (i < 100) {
// nested loops with something in between
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">while</warning> (i < 5) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">while</warning> (i < 5) {
doSomething();
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">while</warning> (i < 10) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">while</warning> (i < 10) {
doSomething();
i++;
}
@@ -23,20 +23,20 @@ class Clazz {
}
// nested loops with a block in between
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">while</warning> (i < 15) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">while</warning> (i < 15) {
if (i != 3) {
//empty loop
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">while</warning> (j > 5) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">while</warning> (j > 5) {
}
}
i++;
}
// single-line loop
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">while</warning> (i < 20) System.out.println(i);
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">while</warning> (i < 20) System.out.println(i);
// no body loop
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">while</warning>(i < 0);
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">while</warning>(i < 0);
i++;
}
@@ -10,7 +10,7 @@ class Clazz {
@RequiresReadLock
public static void foo() {
int i = 0;
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">do<caret></warning> {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">do<caret></warning> {
doSomething();
i++;
}
@@ -11,7 +11,7 @@ class Clazz {
public static void foo() {
String[] items = {""};
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for<caret></warning> (String item : items) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for<caret></warning> (String item : items) {
doSomething();
}
}
@@ -9,7 +9,7 @@ class Clazz {
@RequiresReadLock
public static void foo() {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for<caret></warning> (int i = 0; i < 5; i++) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for<caret></warning> (int i = 0; i < 5; i++) {
doSomething();
}
}
@@ -10,7 +10,7 @@ class Clazz {
@RequiresReadLock
public static void foo() {
int i = 0;
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">while<caret></warning> (i < 5) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">while<caret></warning> (i < 5) {
doSomething();
i++;
}
@@ -8,7 +8,7 @@ class Clazz {
@RequiresReadLock
public static void foo() {
int i = 0;
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">do<caret></warning> {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">do<caret></warning> {
// check comments
}
while (i < 100);
@@ -9,7 +9,7 @@ class Clazz {
public static void foo() {
String[] items = {""};
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for<caret></warning> (String item : items) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for<caret></warning> (String item : items) {
// check comments
}
}
@@ -7,7 +7,7 @@ class Clazz {
@RequiresReadLock
public static void foo() {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for<caret></warning> (int i = 0; i < 5; i++) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for<caret></warning> (int i = 0; i < 5; i++) {
// check comments
}
}
@@ -10,7 +10,7 @@ class Clazz {
@RequiresReadLock
public static void foo() {
int i = 0;
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">while<caret></warning> (i < 5) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">while<caret></warning> (i < 5) {
// check comments
}
}
@@ -11,6 +11,6 @@ class Clazz {
public static void foo() {
String[] items = {""};
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for<caret></warning> (String item : items);
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for<caret></warning> (String item : items);
}
}
@@ -9,6 +9,6 @@ class Clazz {
@RequiresReadLock
public static void foo() {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for<caret></warning> (int i = 0; i < 5; i++);
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for<caret></warning> (int i = 0; i < 5; i++);
}
}
@@ -10,6 +10,6 @@ class Clazz {
@RequiresReadLock
public static void foo() {
int i = 0;
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">while<caret></warning> (i < 5);
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">while<caret></warning> (i < 5);
}
}
@@ -10,7 +10,7 @@ class Clazz {
@RequiresReadLock
public static void foo() {
int i = 0;
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">do<caret></warning> i++;
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">do<caret></warning> i++;
while (i < 100);
}
}
@@ -11,6 +11,6 @@ class Clazz {
public static void foo() {
String[] items = {""};
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for<caret></warning> (String item : items) doSomething();
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for<caret></warning> (String item : items) doSomething();
}
}
@@ -9,6 +9,6 @@ class Clazz {
@RequiresReadLock
public static void foo() {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for<caret></warning> (int i = 0; i < 5; i++) doSomething();
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for<caret></warning> (int i = 0; i < 5; i++) doSomething();
}
}
@@ -10,6 +10,6 @@ class Clazz {
@RequiresReadLock
public static void foo() {
int i = 0;
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">while<caret></warning> (i < 5) i++;
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">while<caret></warning> (i < 5) i++;
}
}
@@ -15,10 +15,18 @@ class CancellationCheckInLoopsInspectionTest : CancellationCheckInLoopsInspectio
doTest()
}
fun testRunConditionOnSuperMethod() {
doTest()
}
fun testPresentCancellationCheck() {
doTest()
}
fun testCancellationCheckPresentNotInFirstLine() {
doTest()
}
fun testForEachLoops() {
doTest()
}
@@ -0,0 +1,38 @@
package inspections.cancellationCheckInLoops
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.progress.checkCancelled
import com.intellij.util.concurrency.annotations.RequiresReadLock
import inspections.cancellationCheckInLoops.Foo.doSomething
@RequiresReadLock
fun main() {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (i in 1..10) {
doSomething()
ProgressManager.checkCanceled()
}
var i = 0;
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">while</warning> (i < 5) {
doSomething()
i++
ProgressManager.checkCanceled()
}
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">do</warning> {
doSomething()
ProgressManager.checkCanceled()
i++
} while (i < 10)
}
@RequiresReadLock
suspend fun foo() {
<warning descr="Cancellation check 'com.intellij.openapi.progress.checkCancelled' should be the first statement in a loop body">for</warning> (i in 1..10) {
doSomething()
checkCancelled()
}
}
@@ -10,9 +10,9 @@ fun main() {
var i = 0
do {
// nested loops with something in between
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">do</warning> {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">do</warning> {
doSomething()
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">do</warning> {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">do</warning> {
doSomething()
i++
} while (i < 20)
@@ -20,22 +20,22 @@ fun main() {
} while (i < 10)
// sibling loop
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">do</warning> {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">do</warning> {
doSomething()
i++
} while (i < 30)
// nested loops with a block in between
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">do</warning> {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">do</warning> {
if (i < 5) {
// empty loop
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">do</warning> {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">do</warning> {
} while (i < 3)
}
} while (i < 40)
// single-line loop
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">do</warning> doSomething() while (i < 50)
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">do</warning> doSomething() while (i < 50)
i++
} while (i < 100)
}
@@ -9,28 +9,28 @@ import inspections.cancellationCheckInLoops.Foo.doSomething
fun main() {
for (i in 1..10) {
// nested loops with something in between
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for</warning> (j in 1..10) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (j in 1..10) {
doSomething()
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for</warning> (k in 1..10) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (k in 1..10) {
doSomething()
}
}
// sibling loop
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for</warning> (j in 1..10) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (j in 1..10) {
doSomething()
}
// nested loops with a block in between
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for</warning> (j in 1..10) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (j in 1..10) {
if (i < 5) {
// empty loop
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for</warning> (k in 1..10) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (k in 1..10) {
}
}
}
// single-line loop
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for</warning> (j in 1..10) doSomething()
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (j in 1..10) doSomething()
}
}
@@ -11,7 +11,7 @@ fun main() {
// nested loops of different kinds
for (i in 1..10) {
while (j < 5) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">do</warning> {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">do</warning> {
doSomething()
j++
} while (j < 3)
@@ -20,7 +20,7 @@ fun main() {
}
// single line nested loops
for (i in 1..10) <warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">while</warning> (j < 5) {
for (i in 1..10) <warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">while</warning> (j < 5) {
doSomething()
j++
}
@@ -25,13 +25,13 @@ fun main() {
@RequiresReadLock
suspend fun foo() {
// right cancellaiton check
// right cancellation check
for (i in 1..10) {
checkCancelled()
}
// wrong cancellation check
<warning descr="Cancellation check 'com.intellij.openapi.progress.checkCancelled' should be placed in the first line">for</warning> (i in 1..10) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.checkCancelled' should be the first statement in a loop body">for</warning> (i in 1..10) {
ProgressManager.checkCanceled()
}
}
@@ -0,0 +1,20 @@
package inspections.cancellationCheckInLoops
import com.intellij.util.concurrency.annotations.RequiresReadLock
import inspections.cancellationCheckInLoops.Foo.doSomething
fun foo() {
for (i in 1..10) {
doSomething()
}
}
@RequiresReadLock
fun bar() {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (i in 1..10) {
doSomething()
}
}
@@ -0,0 +1,23 @@
package inspections.cancellationCheckInLoops
import com.intellij.util.concurrency.annotations.RequiresReadLock
import inspections.cancellationCheckInLoops.Foo.doSomething
abstract class Bar {
@RequiresReadLock
abstract fun bar()
}
class BarImpl : Bar() {
override fun bar() {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for</warning> (i in 1..10) {
doSomething()
}
}
}
@@ -9,7 +9,7 @@ fun withSuspendLambda(l: suspend () -> Any) { }
@RequiresReadLock
suspend fun mySuspendFun() {
<warning descr="Cancellation check 'com.intellij.openapi.progress.checkCancelled' should be placed in the first line">for</warning> (i in 1..10) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.checkCancelled' should be the first statement in a loop body">for</warning> (i in 1..10) {
doSomething()
}
}
@@ -17,7 +17,7 @@ suspend fun mySuspendFun() {
@RequiresReadLock
fun main() {
withSuspendLambda {
<warning descr="Cancellation check 'com.intellij.openapi.progress.checkCancelled' should be placed in the first line">for</warning> (i in 1..10) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.checkCancelled' should be the first statement in a loop body">for</warning> (i in 1..10) {
doSomething()
}
}
@@ -10,9 +10,9 @@ fun main() {
var i = 0
while (i < 100) {
// nested loops with something in between
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">while</warning> (i < 10) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">while</warning> (i < 10) {
doSomething()
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">while</warning> (i < 20) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">while</warning> (i < 20) {
doSomething()
i++
}
@@ -20,22 +20,22 @@ fun main() {
}
// sibling loop
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">while</warning> (i < 30) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">while</warning> (i < 30) {
doSomething()
i++
}
// nested loops with a block in between
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">while</warning> (i < 40) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">while</warning> (i < 40) {
if (i < 5) {
// empty loop
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">while</warning> (i < 3) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">while</warning> (i < 3) {
}
}
}
// single-line loop
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">while</warning> (i < 50) doSomething()
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">while</warning> (i < 50) doSomething()
i++
}
}
@@ -8,7 +8,7 @@ import inspections.cancellationCheckInLoops.Foo.doSomething
@RequiresReadLock
fun main() {
var i = 0
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">do<caret></warning> {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">do<caret></warning> {
// comments
doSomething()
i++
@@ -7,7 +7,7 @@ import inspections.cancellationCheckInLoops.Foo.doSomething
@RequiresReadLock
fun main() {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for<caret></warning> (i in 1..10) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for<caret></warning> (i in 1..10) {
// comments
doSomething()
}
@@ -8,7 +8,7 @@ import inspections.cancellationCheckInLoops.Foo.doSomething
@RequiresReadLock
fun main() {
var i = 0
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">while<caret></warning> (i < 10) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">while<caret></warning> (i < 10) {
// comments
doSomething()
i++
@@ -6,7 +6,7 @@ import com.intellij.util.concurrency.annotations.RequiresReadLock
@RequiresReadLock
fun main() {
var i = 0
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">do<caret></warning> {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">do<caret></warning> {
// comments
} while (i < 10)
}
@@ -5,7 +5,7 @@ import com.intellij.util.concurrency.annotations.RequiresReadLock
@RequiresReadLock
fun main() {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for<caret></warning> (i in 1..10) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for<caret></warning> (i in 1..10) {
// comments
}
}
@@ -6,7 +6,7 @@ import com.intellij.util.concurrency.annotations.RequiresReadLock
@RequiresReadLock
fun main() {
var i = 0
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">while<caret></warning> (i < 10) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">while<caret></warning> (i < 10) {
// comments
}
}
@@ -5,5 +5,5 @@ import com.intellij.util.concurrency.annotations.RequiresReadLock
@RequiresReadLock
fun main() {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for<caret></warning> (i in 1..10); // comments
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for<caret></warning> (i in 1..10); // comments
}
@@ -6,5 +6,5 @@ import com.intellij.util.concurrency.annotations.RequiresReadLock
@RequiresReadLock
fun main() {
var i = 0
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">while<caret></warning> (i < 10);
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">while<caret></warning> (i < 10);
}
@@ -6,5 +6,5 @@ import com.intellij.util.concurrency.annotations.RequiresReadLock
@RequiresReadLock
fun main() {
var i = 0
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">do<caret></warning> i++ while (i < 10) // comments
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">do<caret></warning> i++ while (i < 10) // comments
}
@@ -7,5 +7,5 @@ import inspections.cancellationCheckInLoops.Foo.doSomething
@RequiresReadLock
fun main() {
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">for<caret></warning> (i in 1..10) doSomething() // comments
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">for<caret></warning> (i in 1..10) doSomething() // comments
}
@@ -5,5 +5,5 @@ import com.intellij.util.concurrency.annotations.RequiresReadLock
@RequiresReadLock
fun main() {
var i = 0
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be placed in the first line">while<caret></warning> (i < 10) i++ // comments
<warning descr="Cancellation check 'com.intellij.openapi.progress.ProgressManager.checkCanceled' should be the first statement in a loop body">while<caret></warning> (i < 10) i++ // comments
}
@@ -8,7 +8,7 @@ import inspections.cancellationCheckInLoops.Foo.doSomething
@RequiresReadLock
suspend fun main() {
var i = 0
<warning descr="Cancellation check 'com.intellij.openapi.progress.checkCancelled' should be placed in the first line">do<caret></warning> {
<warning descr="Cancellation check 'com.intellij.openapi.progress.checkCancelled' should be the first statement in a loop body">do<caret></warning> {
// comments
doSomething()
i++
@@ -7,7 +7,7 @@ import inspections.cancellationCheckInLoops.Foo.doSomething
@RequiresReadLock
suspend fun main() {
<warning descr="Cancellation check 'com.intellij.openapi.progress.checkCancelled' should be placed in the first line">for<caret></warning> (i in 1..10) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.checkCancelled' should be the first statement in a loop body">for<caret></warning> (i in 1..10) {
// comments
doSomething()
}
@@ -8,7 +8,7 @@ import inspections.cancellationCheckInLoops.Foo.doSomething
@RequiresReadLock
suspend fun main() {
var i = 0
<warning descr="Cancellation check 'com.intellij.openapi.progress.checkCancelled' should be placed in the first line">while<caret></warning> (i < 10) {
<warning descr="Cancellation check 'com.intellij.openapi.progress.checkCancelled' should be the first statement in a loop body">while<caret></warning> (i < 10) {
// comments
doSomething()
i++
@@ -25,6 +25,14 @@ class KtCancellationCheckInLoopsInspectionTest : CancellationCheckInLoopsInspect
""".trimIndent())
}
fun testRunCondition() {
doTest()
}
fun testRunConditionOnSuperMethod() {
doTest()
}
fun testSuspendingContext() {
doTest()
}
@@ -33,6 +41,10 @@ class KtCancellationCheckInLoopsInspectionTest : CancellationCheckInLoopsInspect
doTest()
}
fun testCancellationCheckPresentNotInFirstLine() {
doTest()
}
fun testForEachLoops() {
doTest()
}