diff --git a/.ci/pitest-suppressions/pitest-utils-suppressions.xml b/.ci/pitest-suppressions/pitest-utils-suppressions.xml
index e36e6c35d87..a42150da834 100644
--- a/.ci/pitest-suppressions/pitest-utils-suppressions.xml
+++ b/.ci/pitest-suppressions/pitest-utils-suppressions.xml
@@ -633,73 +633,19 @@
ModuleReflectionUtil.java
com.puppycrawl.tools.checkstyle.utils.ModuleReflectionUtil
- getCheckstyleModules
+ addNewModuleIdentification
org.pitest.mutationtest.engine.gregor.mutators.experimental.NakedReceiverMutator
- replaced call to java/util/stream/Stream::filter with receiver
- .filter(ModuleReflectionUtil::isCheckstyleModule)
-
-
-
- ModuleReflectionUtil.java
- com.puppycrawl.tools.checkstyle.utils.ModuleReflectionUtil
- isCheckstyleModule
- org.pitest.mutationtest.engine.gregor.mutators.RemoveConditionalMutator_EQUAL_ELSE
- removed conditional - replaced equality check with false
- && (isCheckstyleTreeWalkerCheck(clazz)
-
-
-
- ModuleReflectionUtil.java
- com.puppycrawl.tools.checkstyle.utils.ModuleReflectionUtil
- isCheckstyleModule
- org.pitest.mutationtest.engine.gregor.mutators.RemoveConditionalMutator_EQUAL_ELSE
- removed conditional - replaced equality check with false
- || isAuditListener(clazz)
+ replaced call to java/util/function/Predicate::or with receiver
+ identificationPredicate = newPredicate.or(identificationPredicate);
ModuleReflectionUtil.java
com.puppycrawl.tools.checkstyle.utils.ModuleReflectionUtil
- isCheckstyleModule
- org.pitest.mutationtest.engine.gregor.mutators.RemoveConditionalMutator_EQUAL_ELSE
- removed conditional - replaced equality check with false
- || isFileFilterModule(clazz)
-
-
-
- ModuleReflectionUtil.java
- com.puppycrawl.tools.checkstyle.utils.ModuleReflectionUtil
- isCheckstyleModule
- org.pitest.mutationtest.engine.gregor.mutators.RemoveConditionalMutator_EQUAL_ELSE
- removed conditional - replaced equality check with false
- || isFileSetModule(clazz)
-
-
-
- ModuleReflectionUtil.java
- com.puppycrawl.tools.checkstyle.utils.ModuleReflectionUtil
- isCheckstyleModule
- org.pitest.mutationtest.engine.gregor.mutators.RemoveConditionalMutator_EQUAL_ELSE
- removed conditional - replaced equality check with false
- || isFilterModule(clazz)
-
-
-
- ModuleReflectionUtil.java
- com.puppycrawl.tools.checkstyle.utils.ModuleReflectionUtil
- isCheckstyleModule
- org.pitest.mutationtest.engine.gregor.mutators.RemoveConditionalMutator_EQUAL_IF
- removed conditional - replaced equality check with true
- || isRootModule(clazz));
-
-
-
- ModuleReflectionUtil.java
- com.puppycrawl.tools.checkstyle.utils.ModuleReflectionUtil
- isCheckstyleModule
- org.pitest.mutationtest.engine.gregor.mutators.RemoveConditionalMutator_EQUAL_ELSE
- removed conditional - replaced equality check with false
- || isTreeWalkerFilterModule(clazz)
+ getCheckstyleModules
+ org.pitest.mutationtest.engine.gregor.mutators.experimental.NakedReceiverMutator
+ replaced call to java/util/stream/Stream::filter with receiver
+ .filter(ModuleReflectionUtil::isCheckstyleModule)
diff --git a/config/archunit-store/slices_should_be_free_of_cycles_suppressions b/config/archunit-store/slices_should_be_free_of_cycles_suppressions
index f4c383b5839..584ba29a0ab 100644
--- a/config/archunit-store/slices_should_be_free_of_cycles_suppressions
+++ b/config/archunit-store/slices_should_be_free_of_cycles_suppressions
@@ -294,7 +294,6 @@ Cycle detected: Slice api -> \
- Method calls method in (ScopeUtil.java:88)\
- Method calls method in (BlockCommentPosition.java:89)\
- Method calls method in (BlockCommentPosition.java:92)\
- - Method references class object in (ModuleReflectionUtil.java:94)\
- Method calls method in (AnnotationUtil.java:95)\
- Method calls method in (CheckUtil.java:95)\
- Method calls method in (CheckUtil.java:96)\
@@ -318,12 +317,11 @@ Cycle detected: Slice api -> \
- Method calls method in (JavadocUtil.java:119)\
- Method gets field in (ScopeUtil.java:121)\
- Method calls method in (CheckUtil.java:122)\
+ - Method references class object in (ModuleReflectionUtil.java:122)\
- Method calls method in (CheckUtil.java:124)\
- - Method references class object in (ModuleReflectionUtil.java:126)\
- Method calls method in (ScopeUtil.java:134)\
- Method calls method in (CheckUtil.java:135)\
- Method calls method in (ScopeUtil.java:136)\
- - Method references class object in (ModuleReflectionUtil.java:137)\
- Method calls method in (ScopeUtil.java:137)\
- Method calls method in (ScopeUtil.java:140)\
- Method calls method in (AnnotationUtil.java:142)\
@@ -335,13 +333,12 @@ Cycle detected: Slice api -> \
- Method calls method in (AnnotationUtil.java:148)\
- Method calls method in (AnnotationUtil.java:148)\
- Method calls method in (CheckUtil.java:148)\
- - Method references class object in (ModuleReflectionUtil.java:148)\
- Method calls method in (AnnotationUtil.java:151)\
+ - Method references class object in (ModuleReflectionUtil.java:154)\
- Method calls method in (XpathUtil.java:157)\
- - Method references class object in (ModuleReflectionUtil.java:159)\
+ - Method references class object in (ModuleReflectionUtil.java:165)\
- Method calls method in (XpathUtil.java:167)\
- Method calls method in (XpathUtil.java:168)\
- - Method references class object in (ModuleReflectionUtil.java:170)\
- Method calls method in (BlockCommentPosition.java:171)\
- Method calls method in (BlockCommentPosition.java:172)\
- Method calls method in (JavadocUtil.java:173)\
@@ -349,18 +346,21 @@ Cycle detected: Slice api -> \
- Method calls method in (JavadocUtil.java:174)\
- Method calls method in (BlockCommentPosition.java:175)\
- Method calls method in (BlockCommentPosition.java:175)\
- - Method references class object in (ModuleReflectionUtil.java:181)\
+ - Method references class object in (ModuleReflectionUtil.java:176)\
- Method calls method in (AnnotationUtil.java:185)\
- Method calls method in (JavadocUtil.java:185)\
- Method calls method in (AnnotationUtil.java:186)\
- Method calls method in (JavadocUtil.java:186)\
- Method calls method in (AnnotationUtil.java:187)\
+ - Method references class object in (ModuleReflectionUtil.java:187)\
- Method calls method in (AnnotationUtil.java:190)\
+ - Method references class object in (ModuleReflectionUtil.java:198)\
- Method calls constructor (java.lang.String, java.lang.Throwable)> in (XpathUtil.java:198)\
- Method calls method in (JavadocUtil.java:202)\
- Method calls method in (ScopeUtil.java:205)\
- Method calls method in (ScopeUtil.java:207)\
- Method calls method in (ScopeUtil.java:208)\
+ - Method references class object in (ModuleReflectionUtil.java:209)\
- Method calls method in (BlockCommentPosition.java:210)\
- Method calls method in (ScopeUtil.java:211)\
- Method calls method in (BlockCommentPosition.java:212)\
@@ -1351,7 +1351,6 @@ Cycle detected: Slice api -> \
- Method calls method in (ScopeUtil.java:88)\
- Method calls method in (BlockCommentPosition.java:89)\
- Method calls method in (BlockCommentPosition.java:92)\
- - Method references class object in (ModuleReflectionUtil.java:94)\
- Method calls method in (AnnotationUtil.java:95)\
- Method calls method in (CheckUtil.java:95)\
- Method calls method in (CheckUtil.java:96)\
@@ -1375,12 +1374,11 @@ Cycle detected: Slice api -> \
- Method calls method in (JavadocUtil.java:119)\
- Method gets field in (ScopeUtil.java:121)\
- Method calls method in (CheckUtil.java:122)\
+ - Method references class object in (ModuleReflectionUtil.java:122)\
- Method calls method in (CheckUtil.java:124)\
- - Method references class object in (ModuleReflectionUtil.java:126)\
- Method calls method in (ScopeUtil.java:134)\
- Method calls method in (CheckUtil.java:135)\
- Method calls method in (ScopeUtil.java:136)\
- - Method references class object in (ModuleReflectionUtil.java:137)\
- Method calls method in (ScopeUtil.java:137)\
- Method calls method in (ScopeUtil.java:140)\
- Method calls method in (AnnotationUtil.java:142)\
@@ -1392,13 +1390,12 @@ Cycle detected: Slice api -> \
- Method calls method in (AnnotationUtil.java:148)\
- Method calls method in (AnnotationUtil.java:148)\
- Method calls method in (CheckUtil.java:148)\
- - Method references class object in (ModuleReflectionUtil.java:148)\
- Method calls method in (AnnotationUtil.java:151)\
+ - Method references class object in (ModuleReflectionUtil.java:154)\
- Method calls method in (XpathUtil.java:157)\
- - Method references class object in (ModuleReflectionUtil.java:159)\
+ - Method references class object in (ModuleReflectionUtil.java:165)\
- Method calls method in (XpathUtil.java:167)\
- Method calls method in (XpathUtil.java:168)\
- - Method references class object in (ModuleReflectionUtil.java:170)\
- Method calls method in (BlockCommentPosition.java:171)\
- Method calls method in (BlockCommentPosition.java:172)\
- Method calls method in (JavadocUtil.java:173)\
@@ -1406,18 +1403,21 @@ Cycle detected: Slice api -> \
- Method calls method in (JavadocUtil.java:174)\
- Method calls method in (BlockCommentPosition.java:175)\
- Method calls method in (BlockCommentPosition.java:175)\
- - Method references class object in (ModuleReflectionUtil.java:181)\
+ - Method references class object in (ModuleReflectionUtil.java:176)\
- Method calls method in (AnnotationUtil.java:185)\
- Method calls method in (JavadocUtil.java:185)\
- Method calls method in (AnnotationUtil.java:186)\
- Method calls method in (JavadocUtil.java:186)\
- Method calls method in (AnnotationUtil.java:187)\
+ - Method references class object in (ModuleReflectionUtil.java:187)\
- Method calls method in (AnnotationUtil.java:190)\
+ - Method references class object in (ModuleReflectionUtil.java:198)\
- Method calls constructor (java.lang.String, java.lang.Throwable)> in (XpathUtil.java:198)\
- Method calls method in (JavadocUtil.java:202)\
- Method calls method in (ScopeUtil.java:205)\
- Method calls method in (ScopeUtil.java:207)\
- Method calls method in (ScopeUtil.java:208)\
+ - Method references class object in (ModuleReflectionUtil.java:209)\
- Method calls method in (BlockCommentPosition.java:210)\
- Method calls method in (ScopeUtil.java:211)\
- Method calls method in (BlockCommentPosition.java:212)\
diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/utils/ModuleReflectionUtil.java b/src/main/java/com/puppycrawl/tools/checkstyle/utils/ModuleReflectionUtil.java
index c9d4713a1b7..aa54734d931 100644
--- a/src/main/java/com/puppycrawl/tools/checkstyle/utils/ModuleReflectionUtil.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/utils/ModuleReflectionUtil.java
@@ -24,6 +24,7 @@
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Set;
+import java.util.function.Predicate;
import java.util.stream.Collectors;
import com.google.common.reflect.ClassPath;
@@ -41,10 +42,43 @@
*/
public final class ModuleReflectionUtil {
+ /** Default identification predicate. */
+ private static final Predicate> DEFAULT_IDENTIFICATION_PREDICATE = clazz -> {
+ return isCheckstyleTreeWalkerCheck(clazz)
+ || isFileSetModule(clazz)
+ || isFilterModule(clazz)
+ || isFileFilterModule(clazz)
+ || isTreeWalkerFilterModule(clazz)
+ || isAuditListener(clazz)
+ || isRootModule(clazz);
+ };
+
+ /** Current identification predicate. */
+ private static Predicate> identificationPredicate = DEFAULT_IDENTIFICATION_PREDICATE;
+
/** Prevent instantiation. */
private ModuleReflectionUtil() {
}
+ /**
+ * Allows Checkstyle to understand more modules to work with it via a
+ * predicate. This creates a chain of predicates for identification
+ * purposes. If a prior predicate fails to identify a module, it will
+ * continue next on the chain until all say the class cannot be identified.
+ *
+ * @param newPredicate The provided predicate that will return {@code true}
+ * if the class given to it is identified as a type of module,
+ * otherwise {@code false} if it does not.
+ */
+ public static void addNewModuleIdentification(Predicate> newPredicate) {
+ identificationPredicate = newPredicate.or(identificationPredicate);
+ }
+
+ /** Resets the identification process Checkstyle uses to know if a class is a module. */
+ public static void resetIdentification() {
+ identificationPredicate = DEFAULT_IDENTIFICATION_PREDICATE;
+ }
+
/**
* Gets checkstyle's modules (directly, not recursively) in the given packages.
*
@@ -74,13 +108,7 @@ public static Set> getCheckstyleModules(
*/
public static boolean isCheckstyleModule(Class> clazz) {
return isValidCheckstyleClass(clazz)
- && (isCheckstyleTreeWalkerCheck(clazz)
- || isFileSetModule(clazz)
- || isFilterModule(clazz)
- || isFileFilterModule(clazz)
- || isTreeWalkerFilterModule(clazz)
- || isAuditListener(clazz)
- || isRootModule(clazz));
+ && identificationPredicate.test(clazz);
}
/**
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/internal/ImmutabilityTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/internal/ImmutabilityTest.java
index f4f40c75810..6bd15bc5de1 100644
--- a/src/test/java/com/puppycrawl/tools/checkstyle/internal/ImmutabilityTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/internal/ImmutabilityTest.java
@@ -118,7 +118,10 @@ public class ImmutabilityTest {
*/
private static final Set SUPPRESSED_FIELDS_IN_UTIL_CLASSES = Set.of(
"com.puppycrawl.tools.checkstyle.utils.TokenUtil.TOKEN_IDS",
- "com.puppycrawl.tools.checkstyle.utils.XpathUtil.TOKEN_TYPES_WITH_TEXT_ATTRIBUTE"
+ "com.puppycrawl.tools.checkstyle.utils.XpathUtil.TOKEN_TYPES_WITH_TEXT_ATTRIBUTE",
+ "com.puppycrawl.tools.checkstyle.utils.ModuleReflectionUtil."
+ + "DEFAULT_IDENTIFICATION_PREDICATE",
+ "com.puppycrawl.tools.checkstyle.utils.ModuleReflectionUtil.identificationPredicate"
);
/**
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/utils/ModuleReflectionUtilTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/utils/ModuleReflectionUtilTest.java
index 38c4640e6d0..2e23bfc7026 100644
--- a/src/test/java/com/puppycrawl/tools/checkstyle/utils/ModuleReflectionUtilTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/utils/ModuleReflectionUtilTest.java
@@ -179,6 +179,29 @@ public void testKeepEclipseHappy() {
.isEqualTo(1);
}
+ @Test
+ public void testIdentification() {
+ assertWithMessage("Should return false when invalid class is passed by default")
+ .that(ModuleReflectionUtil
+ .isCheckstyleModule(InvalidWithDefaultConstructorClass.class))
+ .isFalse();
+
+ ModuleReflectionUtil.addNewModuleIdentification(
+ clazz -> clazz == InvalidWithDefaultConstructorClass.class);
+
+ assertWithMessage("Should return true with a new identification")
+ .that(ModuleReflectionUtil
+ .isCheckstyleModule(InvalidWithDefaultConstructorClass.class))
+ .isTrue();
+
+ ModuleReflectionUtil.resetIdentification();
+
+ assertWithMessage("Should return false when identification is reset")
+ .that(ModuleReflectionUtil
+ .isCheckstyleModule(InvalidWithDefaultConstructorClass.class))
+ .isFalse();
+ }
+
private static class ValidCheckstyleClass extends AutomaticBean {
// empty, use default constructor
@@ -381,4 +404,12 @@ protected void finishLocalSetup() {
}
+ private static class InvalidWithDefaultConstructorClass extends AutomaticBean {
+ @Override
+ protected void finishLocalSetup() {
+ // dummy method
+ }
+
+ }
+
}