Unused: avoid flaky behavior by forcing to make reachable content in case of incomplete reachable status

- Example: the class was made reachable as the base class (without making reachable out references), later that class may hit to visit itself.
 - In this case, the content of the class wouldn't be reachable.
 - It can be the source of flaky behavior because the results of the inspection run would depend on the visiting order.

(cherry picked from commit 62d457f7d85ebcf96d5ce990de40d7b0b0b88cfe)

IJ-CR-100952

GitOrigin-RevId: 4a921ebc61aed504030d00dd7ccbc55601c5ba68
This commit is contained in:
Aleksander Movsesov
2023-01-24 09:09:57 +00:00
committed by intellij-monorepo-bot
parent 2135871356
commit aee70454bc
4 changed files with 33 additions and 6 deletions
@@ -594,6 +594,7 @@ public class UnusedDeclarationInspectionBase extends GlobalInspectionTool {
private final Map<RefClass, Set<RefMethod>> myClassIDtoMethods = new HashMap<>();
private final Set<RefClass> myInstantiatedClasses = new HashSet<>();
private int myInstantiatedClassesCount;
private final Set<RefClass> myProcessedClasses = new HashSet<>();
private final Set<RefMethod> myProcessedMethods = new HashSet<>();
private final Set<RefFunctionalExpression> myProcessedFunctionalExpressions = new HashSet<>();
private final Stack<RefElement> myNextRound = new Stack<>();
@@ -646,15 +647,13 @@ public class UnusedDeclarationInspectionBase extends GlobalInspectionTool {
}
@Override public void visitClass(@NotNull RefClass refClass) {
boolean alreadyActive = refClass.isReachable();
((RefClassImpl)refClass).setReachable(true);
if (!alreadyActive) {
if (myProcessedClasses.add(refClass)) {
((RefClassImpl)refClass).setReachable(true);
// Process class's static initializers.
makeReachable(refClass);
}
addInstantiatedClass(refClass);
addInstantiatedClass(refClass);
}
}
@Override public void visitField(@NotNull RefField field) {
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
</problems>
@@ -0,0 +1,20 @@
import java.lang.annotation.*;
public class AnnotationsUtil {
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
private @interface PerClassLifeCycle {
}
@PerClassLifeCycle
private static class BaseMetaAnnotatedTestCase {
}
private static class SpecializedTestCase extends BaseMetaAnnotatedTestCase {
}
public static void main(String[] args) {
System.out.println(SpecializedTestCase.class);
}
}
@@ -131,6 +131,10 @@ public class UnusedDeclarationInspectionTest extends AbstractUnusedDeclarationTe
doTest();
}
public void testAnnotationInitializedByInheritedClassReference() {
doTest();
}
public void testUnusedEnum() {
doTest5();
}