From b3a63541f1641dcda8880503a84ac00cd37e34e6 Mon Sep 17 00:00:00 2001 From: rnveach Date: Sun, 15 May 2022 13:00:42 -0400 Subject: [PATCH] Issue #11604: allows 3rd parties to expand module identification --- .../pitest-utils-suppressions.xml | 68 ++----------------- ...ices_should_be_free_of_cycles_suppressions | 28 ++++---- .../utils/ModuleReflectionUtil.java | 42 ++++++++++-- .../checkstyle/internal/ImmutabilityTest.java | 4 +- .../utils/ModuleReflectionUtilTest.java | 31 +++++++++ 5 files changed, 90 insertions(+), 83 deletions(-) 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..df70b3305d6 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,9 @@ 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 + } + + } + }