From a1e6202d97a6c54a45e8b200e7952b04c85dbd9c Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Wed, 18 Mar 2020 12:32:30 +0000 Subject: [PATCH] Disable sevntu (#284) * Add details from 5.3.6 * Add dependencies for 5.4.0 so-far * Update CI to use install target Using package was missing some lifecycle steps. * Rollback checkstyle to 8.20 - to fix build * Convert RuleSource from enum to configuration file * Split out sevntu plugin version - has own lifecycle * Upgrade sevntu from 1.35.0 to 1.37.1 * Tweak to use java version where ide can see it * Upgrade checkstyle back to 8.29 and disable sevntu rules The sevntu rules are incompatible with checkstyle 8.21+ --- .github/workflows/maven-build.yml | 2 +- .github/workflows/sonatype-deploy.yml | 2 +- CHANGELOG.org | 73 +++++ README.md | 293 +++++++++--------- builder/pom.xml | 7 +- .../ruleset/builder/BuilderConfiguration.java | 7 +- .../ruleset/builder/CheckstyleWriter.java | 28 +- .../builder/DefaultRuleClassLocator.java | 33 +- .../builder/DefaultRuleReadmeLoader.java | 5 +- .../ruleset/builder/FileReader.java | 27 ++ .../ruleset/builder/FileWriter.java | 31 ++ .../ruleset/builder/ReadmeBuilder.java | 36 +++ .../ruleset/builder/ReadmeWriter.java | 62 +--- .../checkstyle/ruleset/builder/Rule.java | 32 +- .../ruleset/builder/RuleLoader.java | 63 ++++ .../ruleset/builder/RuleSource.java | 24 +- .../ruleset/builder/SourcesProperties.java | 30 ++ builder/src/main/resources/application.yml | 11 +- .../builder/BuilderConfigurationTest.java | 19 +- .../ruleset/builder/CheckstyleWriterTest.java | 16 +- .../builder/ClassGraphPackageScannerTest.java | 12 +- .../DefaultReadmeIndexBuilderTest.java | 16 +- .../builder/DefaultRuleClassLocatorTest.java | 37 ++- .../ruleset/builder/FileWriterReaderTest.java | 41 +++ .../ruleset/builder/ReadmeBuilderTest.java | 48 +++ .../ruleset/builder/ReadmeWriterTest.java | 112 +++---- .../ruleset/builder/RuleLoaderTest.java | 130 ++++++++ .../ruleset/builder/RuleSourceMother.java | 34 ++ .../ruleset/builder/RuleSourceTest.java | 34 +- .../checkstyle/ruleset/builder/RuleTest.java | 8 +- .../builder/SourcesPropertiesTest.java | 31 ++ .../net/kemitix/checkstyle-1-layout.xml | 8 +- .../net/kemitix/checkstyle-2-naming.xml | 12 +- .../net/kemitix/checkstyle-3-javadoc.xml | 12 +- .../net/kemitix/checkstyle-4-tweaks.xml | 32 +- .../net/kemitix/checkstyle-5-complexity.xml | 38 +-- 36 files changed, 938 insertions(+), 468 deletions(-) create mode 100644 builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/FileReader.java create mode 100644 builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/FileWriter.java create mode 100644 builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/ReadmeBuilder.java create mode 100644 builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/RuleLoader.java create mode 100644 builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/SourcesProperties.java create mode 100644 builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/FileWriterReaderTest.java create mode 100644 builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/ReadmeBuilderTest.java create mode 100644 builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/RuleLoaderTest.java create mode 100644 builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/RuleSourceMother.java create mode 100644 builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/SourcesPropertiesTest.java diff --git a/.github/workflows/maven-build.yml b/.github/workflows/maven-build.yml index 9ef93b2..8799101 100644 --- a/.github/workflows/maven-build.yml +++ b/.github/workflows/maven-build.yml @@ -24,4 +24,4 @@ jobs: with: java-version: ${{ matrix.java }} - name: Build with Maven - run: mvn -B package --file pom.xml + run: mvn -B install diff --git a/.github/workflows/sonatype-deploy.yml b/.github/workflows/sonatype-deploy.yml index 3068ff8..0db51e7 100644 --- a/.github/workflows/sonatype-deploy.yml +++ b/.github/workflows/sonatype-deploy.yml @@ -14,7 +14,7 @@ jobs: with: java-version: 1.8 - name: Build with Maven - run: mvn -B package + run: mvn -B install - name: Nexus Repo Publish run: sh .github/deploy.sh env: diff --git a/CHANGELOG.org b/CHANGELOG.org index 725937d..d433386 100644 --- a/CHANGELOG.org +++ b/CHANGELOG.org @@ -5,6 +5,79 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +* [5.4.0] - 2020-03-17 + +** Changed + + - Replace Jenkins with Github Actions for CI (#282) + +** Dependencies + + * Bump checkstyle from 8.20 to 8.29 (#268) + * Bump tiles-maven-plugin from 2.15 to 2.16 (#256) + * Bump maven-checkstyle-plugin from 3.1.0 to 3.1.1 (#274) + * Bump kemitix-parent from 5.2.0 to 5.3.0 (#281) + * Bump classgraph from 4.8.48 to 4.8.65 (#276) + * Bump assertj-core from 3.13.2 to 3.15.0 (#269) + * Bump mockito-core from 3.1.0 to 3.3.3 (#280) + * fix: builder/pom.xml to reduce vulnerabilities (#234) + * Bump classgraph from 4.8.47 to 4.8.48 (#242) + * Bump spring-boot.version from 2.1.8.RELEASE to 2.1.9.RELEASE (#241) + * Bump mockito-core from 3.0.0 to 3.1.0 (#240) + * Bump spring-boot.version from 2.1.7.RELEASE to 2.1.8.RELEASE (#236) + * Bump lombok from 1.18.8 to 1.18.10 (#238) + * Bump mapstream from 3.1.17 to 3.1.18 (#237) + * Bump mapstream from 3.1.16 to 3.1.17 (#229) + * Bump classgraph from 4.8.43 to 4.8.47 (#233) + * Bump spring-boot.version from 2.1.6.RELEASE to 2.1.7.RELEASE (#228) + * Bump assertj-core from 3.12.2 to 3.13.2 (#227) + * Bump sevntu.version from 1.34.1 to 1.35.0 (#223) + * Bump mockito-core from 2.27.0 to 3.0.0 (#222) + * Bump classgraph from 4.8.41 to 4.8.43 (#221) + * Bump sevntu.version from 1.34.0 to 1.34.1 (#218) + * Bump tiles-maven-plugin from 2.14 to 2.15 (#217) + * Bump sevntu.version from 1.33.0 to 1.34.0 (#216) + * Bump spring-boot.version from 2.1.5.RELEASE to 2.1.6.RELEASE (#215) + * Bump classgraph from 4.8.38 to 4.8.41 (#214) + * Bump classgraph from 4.8.37 to 4.8.38 (#212) + * Bump maven-checkstyle-plugin from 3.0.0 to 3.1.0 (#208) + * Bump classgraph from 4.8.36 to 4.8.37 (#209) + * Bump lombok from 1.18.6 to 1.18.8 (#201) + * Bump classgraph from 4.8.35 to 4.8.36 (#207) + * Bump spring-boot.version from 2.1.4.RELEASE to 2.1.5.RELEASE (#206) + * Bump classgraph from 4.8.34 to 4.8.35 (#205) + * Bump classgraph from 4.8.31 to 4.8.34 (#204) + * Bump classgraph from 4.8.30 to 4.8.31 (#203) + * Bump classgraph from 4.8.29 to 4.8.30 (#202) + * Bump classgraph from 4.8.26 to 4.8.29 (#199) + * Bump checkstyle from 8.19 to 8.20 (#196) + * Bump tiles-maven-plugin from 2.13 to 2.14 (#200) + * Bump classgraph from 4.8.25 to 4.8.26 (#195) + * Bump classgraph from 4.8.24 to 4.8.25 (#194) + * Bump mockito-core from 2.26.0 to 2.27.0 (#193) + * Bump spring-boot.version from 2.1.3.RELEASE to 2.1.4.RELEASE (#192) + * Bump mapstream from 3.1.15 to 3.1.16 (#191) + * Bump classgraph from 4.8.22 to 4.8.24 (#190) + * Bump mockito-core from 2.25.1 to 2.26.0 (#189) + +* [5.3.6] - 2019-04-05 + +** Dependencies + + - Bump checkstyle from 8.18 to 8.19 (#188) + - Bump classgraph from 4.8.21 to 4.8.22 (#187) + - Bump sevntu.version from 1.32.0 to 1.33.0 (#186) + - Bump mapstream from 3.1.13 to 3.1.15 (#185) + - Bump classgraph from 4.8.17 to 4.8.21 (#184) + - Bump classgraph from 4.8.16 to 4.8.17 (#183) + - Bump classgraph from 4.8.15 to 4.8.16 (#182) + - Bump classgraph from 4.8.14 to 4.8.15 (#181) + - Bump mockito-core from 2.25.0 to 2.25.1 (#180) + - Bump assertj-core from 3.12.1 to 3.12.2 (#179) + - Bump mapstream from 3.1.12 to 3.1.13 (#178) + - Bump classgraph from 4.8.12 to 4.8.14 (#177) + - Bump mockito-core from 2.24.5 to 2.25.0 (#176) + * [5.3.5] - 2019-03-04 ** Removed diff --git a/README.md b/README.md index 87a6d62..0b5eb16 100644 --- a/README.md +++ b/README.md @@ -2072,6 +2072,119 @@ Checks that tokens are surrounded by whitespace. ### Sevntu + + +## Disabled Checks + +These checks are not enabled. Notes are included for each explaining why. + +### Checkstyle + +#### [AbstractClassName](http://checkstyle.sourceforge.net/config_naming.html#AbstractClassName) + +Prevents some more meaningful abstract class names +#### [ArrayTrailingComma](http://checkstyle.sourceforge.net/config_coding.html#ArrayTrailingComma) + +Couldn't get my IDE's (IntelliJ) code style to match. +#### [AvoidStarImport](http://checkstyle.sourceforge.net/config_imports.html#AvoidStarImport) + +Ref: Clean Code, Robert C. Martin, J1: Avoid Long Import Lists by Using Wildcards +#### [AvoidStaticImport](http://checkstyle.sourceforge.net/config_imports.html#AvoidStaticImport) + +Ref: Clean Code, Robert C. Martin, J2: Don't Inherit Constants +Recommends using a static import to access constants from another class over inheriting them. +#### [EmptyLineSeparator](http://checkstyle.sourceforge.net/config_whitespace.html#EmptyLineSeparator) + + +#### [FinalLocalVariable](http://checkstyle.sourceforge.net/config_coding.html#FinalLocalVariable) + +Doesn't recognise Lombok's `val` as being `final`. +#### [Header](http://checkstyle.sourceforge.net/config_header.html#Header) + +Shouldn't need to list in every file, simply listing in project root should be enough. +#### [IllegalInstantiation](http://checkstyle.sourceforge.net/config_coding.html#IllegalInstantiation) + +Not really suitable for a template ruleset as it requires an explicit list of classes to apply to. +#### [IllegalTokenText](http://checkstyle.sourceforge.net/config_coding.html#IllegalTokenText) + +Generic rule; doesn't embody a 'quality' check. +#### [ImportControl](http://checkstyle.sourceforge.net/config_imports.html#ImportControl) + +Generic rule; doesn't embody a 'quality' check. +#### [ImportOrder](http://checkstyle.sourceforge.net/config_imports.html#ImportOrder) + +Generic rule; doesn't embody a 'quality' check. +#### [Indentation](http://checkstyle.sourceforge.net/config_misc.html#Indentation) + +Couldn't get my IDE's (IntelliJ) code style to match. +#### [JavadocMethod](http://checkstyle.sourceforge.net/config_javadoc.html#JavadocMethod) + +Only exceptional cases should need to be documented. +#### [JavadocTagContinuationIndentation](http://checkstyle.sourceforge.net/config_javadoc.html#JavadocTagContinuationIndentation) + +Couldn't get my IDE's (IntelliJ) code style to match. +#### [JavadocVariable](http://checkstyle.sourceforge.net/config_javadoc.html#JavadocVariable) + +Member variables should usually be named such that it is clear what they are. Comments for clarification should be the exception. +#### [MissingCtor](http://checkstyle.sourceforge.net/config_coding.html#MissingCtor) + +Would not see constructors created using Lombok's `@NoArgsConstructor`. +#### [MissingOverride](http://checkstyle.sourceforge.net/config_annotation.html#MissingOverride) + +The javadoc compiler automatically inherits the javadoc from the overridden method, it doesn't need to be told to do so. +#### [OuterTypeNumber](http://checkstyle.sourceforge.net/config_sizes.html#OuterTypeNumber) + +Already covered by the [OneTopLevelClass](#onetoplevelclass) check. +#### [ParameterAssignment](http://checkstyle.sourceforge.net/config_coding.html#ParameterAssignment) + +[FinalParameters](#finalparameters) already protects against assigning values to parameters. +#### [RedundantImport](http://checkstyle.sourceforge.net/config_imports.html#RedundantImport) + +[UnusedImports](#unusedimports) performs all the same checks and more. +#### [RedundantModifier](http://checkstyle.sourceforge.net/config_modifier.html#RedundantModifier) + +conflicts with InterfaceMemberImpliedModifier which is now prefered given changes to interfaces in Java 9 +#### [Regexp](http://checkstyle.sourceforge.net/config_regexp.html#Regexp) + +Generic rule; doesn't embody a 'quality' check. +#### [RegexpHeader](http://checkstyle.sourceforge.net/config_header.html#RegexpHeader) + +Generic rule; doesn't embody a 'quality' check. +#### [RegexpMultiline](http://checkstyle.sourceforge.net/config_regexp.html#RegexpMultiline) + +Generic rule; doesn't embody a 'quality' check. +#### [RegexpOnFilename](http://checkstyle.sourceforge.net/config_regexp.html#RegexpOnFilename) + +Generic rule; doesn't embody a 'quality' check. +#### [RegexpSingleline](http://checkstyle.sourceforge.net/config_regexp.html#RegexpSingleline) + +Generic rule; doesn't embody a 'quality' check. +#### [RegexpSinglelineJava](http://checkstyle.sourceforge.net/config_regexp.html#RegexpSinglelineJava) + +Generic rule; doesn't embody a 'quality' check. +#### [SingleLineJavadoc](http://checkstyle.sourceforge.net/config_javadoc.html#SingleLineJavadoc) + +I don't use single line javadoc blocks. +#### [SummaryJavadoc](http://checkstyle.sourceforge.net/config_javadoc.html#SummaryJavadoc) + +Generic rule; doesn't embody a 'quality' check. +#### [SuperClone](http://checkstyle.sourceforge.net/config_coding.html#SuperClone) + +Overridding the `clone()` method is not allowed by the [NoClone](#noclone) check. +#### [SuperFinalize](http://checkstyle.sourceforge.net/config_coding.html#SuperFinalize) + +[NoFinalizer](#nofinalizer) prevents use of `finalize()`. +#### [WriteTag](http://checkstyle.sourceforge.net/config_javadoc.html#WriteTag) + +Generic rule; doesn't embody a 'quality' check. + +### Sevntu + +As the sevntu check are considered experimental not all those that are not enabled are listed here. Only where they are disabled due to a conflict with my 'style' or there is another irreconcilable difference that prevents them from being enabled, will they be documented to prevent repeated investigations. + +#### [AvoidConditionInversion](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/design/AvoidConditionInversionCheck.html) + +Should already be covered by [SimplifyBooleanExpression](simplifybooleanexpression). #### [AvoidConstantAsFirstOperandInCondition](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/coding/AvoidConstantAsFirstOperandInConditionCheck.html) Checks that condition expressions don't become less readable by attempting to use a constant on the left-hand-side of a comparison. @@ -2109,6 +2222,9 @@ try { throw new MyOtherException(); } ```` +#### [AvoidModifiersForTypes](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/coding/AvoidModifiersForTypesCheck.html) + +Generic rule; doesn't embody a 'quality' check. #### [AvoidNotShortCircuitOperatorsForBoolean](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/coding/AvoidNotShortCircuitOperatorsForBooleanCheck.html) Prevents the use of boolean operators that don't allow short-circuiting the expression. (e.g. '|', '&', '|=' and '&=') @@ -2122,6 +2238,12 @@ Invalid: ```` if ((a < b) | (b > getExpensiveValue())) {} ```` +#### [CauseParameterInException](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/design/CauseParameterInExceptionCheck.html) + +Should already be covered by [AvoidHidingCauseException](#avoidhidingcauseexception). +#### [ChildBlockLength](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/design/ChildBlockLengthCheck.html) + +Appears to be broken as of `1.21.0`. #### [ConfusingCondition](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/coding/ConfusingConditionCheck.html) Checks that the expression with the `if` condition in an `if-then-else` statement is not negated. @@ -2146,6 +2268,9 @@ if (!isValid()) { #### [ConstructorWithoutParams](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/design/ConstructorWithoutParamsCheck.html) Exception class constructors must accept parameters for message and/or cause. This check is applied to classes whose name ends with `Exception`. +#### [CustomDeclarationOrder](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/coding/CustomDeclarationOrderCheck.html) + +The [DeclarationOrder](#declarationorder) check already imposes an order for class elements. #### [DiamondOperatorForVariableDefinition](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/coding/DiamondOperatorForVariableDefinitionCheck.html) Checks that the diamond operator is used where possible. @@ -2252,6 +2377,9 @@ class InvalidPublic { } } ``` +#### [ForbidAnnotation](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/annotation/ForbidAnnotationCheck.html) + +Generic rule; doesn't embody a 'quality' check. #### [ForbidCCommentsInMethods](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/coding/ForbidCCommentsInMethodsCheck.html) Prevents the use of `/* C-style */` comments inside methods. @@ -2269,6 +2397,12 @@ void doSomething() { /* invalid */ } ```` +#### [ForbidCertainImports](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/coding/ForbidCertainImportsCheck.html) + +Generic rule; doesn't embody a 'quality' check. +#### [ForbidInstantiation](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/coding/ForbidInstantiationCheck.html) + +Generic rule; doesn't embody a 'quality' check. #### [ForbidReturnInFinallyBlock](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/coding/ForbidReturnInFinallyBlockCheck.html) Prevent the use of a `return` statement in the `finally` block. @@ -2283,6 +2417,9 @@ try { return true; // invalid } ```` +#### [ForbidThrowAnonymousExceptions](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/coding/ForbidThrowAnonymousExceptionsCheck.html) + +[IllegalThrows](#illegalthrows) performs a similar check. #### [ForbidWildcardAsReturnType](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/design/ForbidWildcardAsReturnTypeCheck.html) Prevents declaring a method from returning a wildcard type as its return value. @@ -2459,6 +2596,9 @@ void doStuff() { return; } ```` +#### [RequiredParameterForAnnotation](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/annotation/RequiredParameterForAnnotationCheck.html) + +Generic rule; doesn't embody a 'quality' check. #### [ReturnBooleanFromTernary](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/coding/ReturnBooleanFromTernaryCheck.html) Ternary statements shouldn't have `Boolean` values as results. @@ -2490,9 +2630,15 @@ Boolean isEnabled() { return null; } ```` +#### [SimpleAccessorNameNotation](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/coding/SimpleAccessorNameNotationCheck.html) + +allow use of non-bean property-like naming #### [SingleBreakOrContinue](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/coding/SingleBreakOrContinueCheck.html) Checks that there is at most one `continue` or `break` statement within a looping block (e.g. `for`, `while`, ...) +#### [StaticMethodCandidate](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/design/StaticMethodCandidateCheck.html) + +Can't handle private methods called by reflection, which may cause issues with Spring and other DI frameworks. #### [TernaryPerExpressionCount](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/coding/TernaryPerExpressionCountCheck.html) Checks that there is at most one ternary statments (`?:`) within an expression. @@ -2570,149 +2716,4 @@ Invalid: int[] ints = new int[]{0, 1, 2, 3}; ```` -## Disabled Checks - -These checks are not enabled. Notes are included for each explaining why. - -### Checkstyle - -#### [AbstractClassName](http://checkstyle.sourceforge.net/config_naming.html#AbstractClassName) - -Prevents some more meaningful abstract class names -#### [ArrayTrailingComma](http://checkstyle.sourceforge.net/config_coding.html#ArrayTrailingComma) - -Couldn't get my IDE's (IntelliJ) code style to match. -#### [AvoidStarImport](http://checkstyle.sourceforge.net/config_imports.html#AvoidStarImport) - -Ref: Clean Code, Robert C. Martin, J1: Avoid Long Import Lists by Using Wildcards -#### [AvoidStaticImport](http://checkstyle.sourceforge.net/config_imports.html#AvoidStaticImport) - -Ref: Clean Code, Robert C. Martin, J2: Don't Inherit Constants -Recommends using a static import to access constants from another class over inheriting them. -#### [EmptyLineSeparator](http://checkstyle.sourceforge.net/config_whitespace.html#EmptyLineSeparator) - - -#### [FinalLocalVariable](http://checkstyle.sourceforge.net/config_coding.html#FinalLocalVariable) - -Doesn't recognise Lombok's `val` as being `final`. -#### [Header](http://checkstyle.sourceforge.net/config_header.html#Header) - -Shouldn't need to list in every file, simply listing in project root should be enough. -#### [IllegalInstantiation](http://checkstyle.sourceforge.net/config_coding.html#IllegalInstantiation) - -Not really suitable for a template ruleset as it requires an explicit list of classes to apply to. -#### [IllegalTokenText](http://checkstyle.sourceforge.net/config_coding.html#IllegalTokenText) - -Generic rule; doesn't embody a 'quality' check. -#### [ImportControl](http://checkstyle.sourceforge.net/config_imports.html#ImportControl) - -Generic rule; doesn't embody a 'quality' check. -#### [ImportOrder](http://checkstyle.sourceforge.net/config_imports.html#ImportOrder) - -Generic rule; doesn't embody a 'quality' check. -#### [Indentation](http://checkstyle.sourceforge.net/config_misc.html#Indentation) - -Couldn't get my IDE's (IntelliJ) code style to match. -#### [JavadocMethod](http://checkstyle.sourceforge.net/config_javadoc.html#JavadocMethod) - -Only exceptional cases should need to be documented. -#### [JavadocTagContinuationIndentation](http://checkstyle.sourceforge.net/config_javadoc.html#JavadocTagContinuationIndentation) - -Couldn't get my IDE's (IntelliJ) code style to match. -#### [JavadocVariable](http://checkstyle.sourceforge.net/config_javadoc.html#JavadocVariable) - -Member variables should usually be named such that it is clear what they are. Comments for clarification should be the exception. -#### [MissingCtor](http://checkstyle.sourceforge.net/config_coding.html#MissingCtor) - -Would not see constructors created using Lombok's `@NoArgsConstructor`. -#### [MissingOverride](http://checkstyle.sourceforge.net/config_annotation.html#MissingOverride) - -The javadoc compiler automatically inherits the javadoc from the overridden method, it doesn't need to be told to do so. -#### [OuterTypeNumber](http://checkstyle.sourceforge.net/config_sizes.html#OuterTypeNumber) - -Already covered by the [OneTopLevelClass](#onetoplevelclass) check. -#### [ParameterAssignment](http://checkstyle.sourceforge.net/config_coding.html#ParameterAssignment) - -[FinalParameters](#finalparameters) already protects against assigning values to parameters. -#### [RedundantImport](http://checkstyle.sourceforge.net/config_imports.html#RedundantImport) - -[UnusedImports](#unusedimports) performs all the same checks and more. -#### [RedundantModifier](http://checkstyle.sourceforge.net/config_modifier.html#RedundantModifier) - -conflicts with InterfaceMemberImpliedModifier which is now prefered given changes to interfaces in Java 9 -#### [Regexp](http://checkstyle.sourceforge.net/config_regexp.html#Regexp) - -Generic rule; doesn't embody a 'quality' check. -#### [RegexpHeader](http://checkstyle.sourceforge.net/config_header.html#RegexpHeader) - -Generic rule; doesn't embody a 'quality' check. -#### [RegexpMultiline](http://checkstyle.sourceforge.net/config_regexp.html#RegexpMultiline) - -Generic rule; doesn't embody a 'quality' check. -#### [RegexpOnFilename](http://checkstyle.sourceforge.net/config_regexp.html#RegexpOnFilename) - -Generic rule; doesn't embody a 'quality' check. -#### [RegexpSingleline](http://checkstyle.sourceforge.net/config_regexp.html#RegexpSingleline) - -Generic rule; doesn't embody a 'quality' check. -#### [RegexpSinglelineJava](http://checkstyle.sourceforge.net/config_regexp.html#RegexpSinglelineJava) - -Generic rule; doesn't embody a 'quality' check. -#### [SingleLineJavadoc](http://checkstyle.sourceforge.net/config_javadoc.html#SingleLineJavadoc) - -I don't use single line javadoc blocks. -#### [SummaryJavadoc](http://checkstyle.sourceforge.net/config_javadoc.html#SummaryJavadoc) - -Generic rule; doesn't embody a 'quality' check. -#### [SuperClone](http://checkstyle.sourceforge.net/config_coding.html#SuperClone) - -Overridding the `clone()` method is not allowed by the [NoClone](#noclone) check. -#### [SuperFinalize](http://checkstyle.sourceforge.net/config_coding.html#SuperFinalize) - -[NoFinalizer](#nofinalizer) prevents use of `finalize()`. -#### [WriteTag](http://checkstyle.sourceforge.net/config_javadoc.html#WriteTag) - -Generic rule; doesn't embody a 'quality' check. - -### Sevntu - -As the sevntu check are considered experimental not all those that are not enabled are listed here. Only where they are disabled due to a conflict with my 'style' or there is another irreconcilable difference that prevents them from being enabled, will they be documented to prevent repeated investigations. - -#### [AvoidConditionInversion](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/design/AvoidConditionInversionCheck.html) - -Should already be covered by [SimplifyBooleanExpression](simplifybooleanexpression). -#### [AvoidModifiersForTypes](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/coding/AvoidModifiersForTypesCheck.html) - -Generic rule; doesn't embody a 'quality' check. -#### [CauseParameterInException](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/design/CauseParameterInExceptionCheck.html) - -Should already be covered by [AvoidHidingCauseException](#avoidhidingcauseexception). -#### [ChildBlockLength](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/design/ChildBlockLengthCheck.html) - -Appears to be broken as of `1.21.0`. -#### [CustomDeclarationOrder](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/coding/CustomDeclarationOrderCheck.html) - -The [DeclarationOrder](#declarationorder) check already imposes an order for class elements. -#### [ForbidAnnotation](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/annotation/ForbidAnnotationCheck.html) - -Generic rule; doesn't embody a 'quality' check. -#### [ForbidCertainImports](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/coding/ForbidCertainImportsCheck.html) - -Generic rule; doesn't embody a 'quality' check. -#### [ForbidInstantiation](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/coding/ForbidInstantiationCheck.html) - -Generic rule; doesn't embody a 'quality' check. -#### [ForbidThrowAnonymousExceptions](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/coding/ForbidThrowAnonymousExceptionsCheck.html) - -[IllegalThrows](#illegalthrows) performs a similar check. -#### [RequiredParameterForAnnotation](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/annotation/RequiredParameterForAnnotationCheck.html) - -Generic rule; doesn't embody a 'quality' check. -#### [SimpleAccessorNameNotation](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/coding/SimpleAccessorNameNotationCheck.html) - -allow use of non-bean property-like naming -#### [StaticMethodCandidate](http://sevntu-checkstyle.github.io/sevntu.checkstyle/apidocs/com/github/sevntu/checkstyle/checks/design/StaticMethodCandidateCheck.html) - -Can't handle private methods called by reflection, which may cause issues with Spring and other DI frameworks. - -[Effective Java]: http://amzn.to/2aSz6GE +[Effective Java]: http://amzn.to/2aSz6GE \ No newline at end of file diff --git a/builder/pom.xml b/builder/pom.xml index 2fe9a6e..6776207 100644 --- a/builder/pom.xml +++ b/builder/pom.xml @@ -19,11 +19,14 @@ true 1.8 + ${java.version} + ${java.version} 2.16 1.1.0 8.30 - 1.35.0 + 1.37.1 + 1.35.0 1.18.10 Brussels-SR6 2.1.9.RELEASE @@ -176,7 +179,7 @@ com.github.sevntu-checkstyle sevntu-checkstyle-maven-plugin - ${sevntu.version} + ${sevntu-plugin.version} net.kemitix.checkstyle diff --git a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/BuilderConfiguration.java b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/BuilderConfiguration.java index b4ba8fa..a69ed7f 100644 --- a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/BuilderConfiguration.java +++ b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/BuilderConfiguration.java @@ -1,5 +1,6 @@ package net.kemitix.checkstyle.ruleset.builder; +import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -7,7 +8,6 @@ import java.util.AbstractMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import java.util.stream.Stream; /** * Configuration for Builder. @@ -15,8 +15,11 @@ import java.util.stream.Stream; * @author Paul Campbell (pcampbell@kemitix.net). */ @Configuration +@RequiredArgsConstructor public class BuilderConfiguration { + private final SourcesProperties sourcesProperties; + /** * A Map of rules for each RuleSource. * @@ -26,7 +29,7 @@ public class BuilderConfiguration { */ @Bean public Map> checkClasses(final PackageScanner packageScanner) { - return Stream.of(RuleSource.values()) + return sourcesProperties.getSources().stream() .map(source -> entry(source, packageScanner.apply(source))) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } diff --git a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleWriter.java b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleWriter.java index 320b7ad..50533cc 100644 --- a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleWriter.java +++ b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleWriter.java @@ -5,11 +5,14 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; +import javax.annotation.PostConstruct; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; +import java.util.HashSet; +import java.util.Set; import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -34,6 +37,19 @@ class CheckstyleWriter implements CommandLineRunner { private final RuleClassLocator ruleClassLocator; + private final SourcesProperties sourcesProperties; + private final Set enabledSourceNames = new HashSet<>(); + + @PostConstruct + public void init() { + enabledSourceNames.addAll( + sourcesProperties.getSources() + .stream() + .filter(RuleSource::isEnabled) + .map(RuleSource::getName) + .collect(Collectors.toSet())); + } + private static Predicate excludeUnspecifiedRuleLevel() { return level -> !level.equals(RuleLevel.UNSPECIFIED); } @@ -41,7 +57,7 @@ class CheckstyleWriter implements CommandLineRunner { private static void writeRuleset( final Path filePath, final String content - ) throws IOException { + ) throws IOException { Files.write(filePath, asList(content.split(System.lineSeparator())), StandardCharsets.UTF_8); } @@ -49,7 +65,7 @@ class CheckstyleWriter implements CommandLineRunner { final String checkerRules, final String treeWalkerRules, final String template - ) { + ) { return String.format(template, checkerRules, treeWalkerRules); } @@ -62,7 +78,7 @@ class CheckstyleWriter implements CommandLineRunner { final String checkerRules, final String treeWalkerRules, final Path template - ) throws IOException { + ) throws IOException { if (fileExists(template.toFile())) { log.info("Writing ruleset: {}", outputPath); final String xmlTemplate = new String(Files.readAllBytes(template), StandardCharsets.UTF_8); @@ -94,19 +110,21 @@ class CheckstyleWriter implements CommandLineRunner { private Path outputPath(final RuleLevel ruleLevel) { return outputProperties.getDirectory() .resolve(outputProperties.getRulesetFiles() - .get(ruleLevel)); + .get(ruleLevel)); } private String enabledRules( final RuleLevel ruleLevel, final RuleParent ruleParent - ) { + ) { return rulesProperties.getRules() .stream() .filter(Rule::isEnabled) + .filter(rule -> enabledSourceNames.contains(rule.getSource())) .filter(Rule.hasParent(ruleParent)) .filter(Rule.isIncludedInLevel(ruleLevel)) .map(rule -> Rule.asModule(ruleClassLocator.apply(rule), rule)) .collect(Collectors.joining(System.lineSeparator())); } + } diff --git a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/DefaultRuleClassLocator.java b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/DefaultRuleClassLocator.java index e329f99..9891dc3 100644 --- a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/DefaultRuleClassLocator.java +++ b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/DefaultRuleClassLocator.java @@ -1,9 +1,9 @@ package net.kemitix.checkstyle.ruleset.builder; -import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Objects; @@ -13,10 +13,18 @@ import java.util.Objects; * @author Paul Campbell (pcampbell@kemitix.net). */ @Service -@RequiredArgsConstructor +//@RequiredArgsConstructor public class DefaultRuleClassLocator implements RuleClassLocator { private final Map> checkClasses; + private final SourcesProperties sourcesProperties; + + public DefaultRuleClassLocator( + final Map> checkClasses, + final SourcesProperties sourcesProperties) { + this.checkClasses = checkClasses; + this.sourcesProperties = sourcesProperties; + } @Override public final String apply(final Rule rule) { @@ -24,23 +32,26 @@ public class DefaultRuleClassLocator implements RuleClassLocator { } private String getCanonicalClassName( - final RuleSource source, + final String sourceName, final String name - ) { + ) { Objects.requireNonNull(checkClasses, "init() method not called"); - return checkClasses.get(source) - .stream() - .sorted() - .filter(classname -> byRuleName(classname, name)) - .findFirst() + return sourcesProperties.findSource(sourceName.toLowerCase(Locale.ENGLISH)) + .map(checkClasses::get) + .flatMap(classes -> + classes.stream() + .sorted() + .filter(className -> byRuleName(className, name)) + .findFirst()) .orElseThrow(() -> new CheckstyleClassNotFoundException(name)); } private boolean byRuleName( final String classname, final String name - ) { + ) { final String classNameWithDelimiter = "." + name; - return classname.endsWith(classNameWithDelimiter) || classname.endsWith(classNameWithDelimiter + "Check"); + return classname.endsWith(classNameWithDelimiter) + || classname.endsWith(classNameWithDelimiter + "Check"); } } diff --git a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/DefaultRuleReadmeLoader.java b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/DefaultRuleReadmeLoader.java index beb3c66..7202231 100644 --- a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/DefaultRuleReadmeLoader.java +++ b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/DefaultRuleReadmeLoader.java @@ -24,8 +24,9 @@ class DefaultRuleReadmeLoader implements RuleReadmeLoader { @Override public Stream load(final Rule rule) { if (rule.isEnabled()) { - final Path resolve = templateProperties.getReadmeFragments() - .resolve(rule.getName() + ".md"); + final Path resolve = + templateProperties.getReadmeFragments() + .resolve(rule.getName() + ".md"); log.info("Loading fragment: {}", resolve); try { return Stream.concat(Stream.of(formatRuleHeader(rule)), Files.lines(resolve)); diff --git a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/FileReader.java b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/FileReader.java new file mode 100644 index 0000000..d6f8614 --- /dev/null +++ b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/FileReader.java @@ -0,0 +1,27 @@ +package net.kemitix.checkstyle.ruleset.builder; + +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; + +@Component +public class FileReader { + private static final String NEWLINE = "\n"; + + /** + * Reads the content from the file path. + * + *

File content will be read using UTF-8 encoding and line endings will + * be replaced with a newline (\n).

+ * + * @param path the file to read + * @throws IOException if there is an error. + */ + public String read(final Path path) throws IOException { + return String.join(NEWLINE, + Files.readAllLines(path, StandardCharsets.UTF_8)); + } +} diff --git a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/FileWriter.java b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/FileWriter.java new file mode 100644 index 0000000..3356e10 --- /dev/null +++ b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/FileWriter.java @@ -0,0 +1,31 @@ +package net.kemitix.checkstyle.ruleset.builder; + +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; + +@Component +public class FileWriter { + + /** + * Writes the content to the file path, replacing any existing file. + * + *

File content will be written using UTF-8 encoding.

+ * + * @param path the file to write + * @param content the content to write + * @throws IOException if there is an error. + */ + public void write( + final Path path, + final String content + ) throws IOException { + Files.write(path, + content.getBytes(StandardCharsets.UTF_8), + StandardOpenOption.TRUNCATE_EXISTING); + } +} diff --git a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/ReadmeBuilder.java b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/ReadmeBuilder.java new file mode 100644 index 0000000..847fddb --- /dev/null +++ b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/ReadmeBuilder.java @@ -0,0 +1,36 @@ +package net.kemitix.checkstyle.ruleset.builder; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class ReadmeBuilder { + + public static final String CHECKSTYLE = "checkstyle"; + public static final String SEVNTU = "sevntu"; + + private final ReadmeIndexBuilder indexBuilder; + private final RuleLoader ruleLoader; + + /** + * Creates a readme based on the template, inserting lists of the enabled + * and disabled checkstyle and sevntu rules. + * + * @param readmeTemplate the String.format compatible template + * @return the formatted readme document. + */ + public String build(final String readmeTemplate) { + String enabledCheckstyle = ruleLoader.loadEnabled(CHECKSTYLE); + String enabledSevntu = ruleLoader.loadEnabled(SEVNTU); + String disabledCheckstyle = ruleLoader.loadDisabled(CHECKSTYLE); + String disabledSevntu = ruleLoader.loadDisabled(SEVNTU); + return String.format(readmeTemplate, + indexBuilder.build(), + enabledCheckstyle, + enabledSevntu, + disabledCheckstyle, + disabledSevntu); + } + +} diff --git a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/ReadmeWriter.java b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/ReadmeWriter.java index 47f374b..2c9bf75 100644 --- a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/ReadmeWriter.java +++ b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/ReadmeWriter.java @@ -4,13 +4,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.StandardOpenOption; -import java.util.function.Predicate; -import java.util.stream.Collectors; /** * Writes the README file. @@ -21,59 +15,19 @@ import java.util.stream.Collectors; @RequiredArgsConstructor class ReadmeWriter implements CommandLineRunner { - private static final String NEWLINE = "\n"; - private final TemplateProperties templateProperties; - private final OutputProperties outputProperties; - - private final RulesProperties rulesProperties; - - private final RuleReadmeLoader ruleReadmeLoader; - - private final ReadmeIndexBuilder indexBuilder; + private final ReadmeBuilder readmeBuilder; + private final FileReader fileReader; + private final FileWriter fileWriter; @Override public void run(final String... args) throws Exception { - final String readmeTemplate = readFile(templateProperties.getReadmeTemplate()); - final String enabledCheckstyle = readmeRules(this::isEnabledCheckstyleRule); - final String enabledSevntu = readmeRules(this::isEnabledSevntuRule); - final String disabledCheckstyle = readmeRules(this::isDisabledCheckstyleRule); - final String disabledSevntu = readmeRules(this::isDisabledSevntuRule); - final byte[] readme = String.format(readmeTemplate, indexBuilder.build(), enabledCheckstyle, enabledSevntu, - disabledCheckstyle, disabledSevntu - ) - .getBytes(StandardCharsets.UTF_8); - Files.write(outputProperties.getReadme(), readme, StandardOpenOption.TRUNCATE_EXISTING); - } - - private boolean isEnabledSevntuRule(final Rule rule) { - return rule.isEnabled() && RuleSource.SEVNTU.equals(rule.getSource()); - } - - private boolean isEnabledCheckstyleRule(final Rule rule) { - return rule.isEnabled() && RuleSource.CHECKSTYLE.equals(rule.getSource()); - } - - private boolean isDisabledSevntuRule(final Rule rule) { - return !rule.isEnabled() && RuleSource.SEVNTU.equals(rule.getSource()); - } - - private boolean isDisabledCheckstyleRule(final Rule rule) { - return !rule.isEnabled() && RuleSource.CHECKSTYLE.equals(rule.getSource()); - } - - private String readmeRules(final Predicate predicate) { - return rulesProperties.getRules() - .stream() - .filter(predicate) - .sorted(Rule::sortByName) - .flatMap(ruleReadmeLoader::load) - .collect(Collectors.joining(NEWLINE)); - } - - private String readFile(final Path file) throws IOException { - return String.join(NEWLINE, Files.readAllLines(file, StandardCharsets.UTF_8)); + Path templatePath = templateProperties.getReadmeTemplate(); + String templateBody = fileReader.read(templatePath); + Path outputPath = outputProperties.getReadme(); + String outputBody = readmeBuilder.build(templateBody); + fileWriter.write(outputPath, outputBody); } } diff --git a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/Rule.java b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/Rule.java index 5c794c8..dc34fe5 100644 --- a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/Rule.java +++ b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/Rule.java @@ -55,7 +55,7 @@ public class Rule { /** * The source of the rule. */ - private RuleSource source; + private String source; /** * URI for full official documentation. @@ -83,8 +83,8 @@ public class Rule { * string. */ protected static int sortByName(final Rule left, final Rule right) { - return left.getLowerCaseRuleName() - .compareTo(right.getLowerCaseRuleName()); + return left.getName().toLowerCase(LOCALE) + .compareTo(right.getName().toLowerCase(LOCALE)); } /** @@ -132,7 +132,7 @@ public class Rule { static String asModule( final String ruleClassname, final Rule rule - ) { + ) { if (hasProperties(rule)) { return moduleWithParameters(rule, ruleClassname); } else { @@ -142,18 +142,34 @@ public class Rule { private static String moduleNoParameters( final String ruleClassname - ) { + ) { return String.format(MODULE_NO_PROPERTIES, ruleClassname); } private static String moduleWithParameters( final Rule rule, final String ruleClassname - ) { + ) { return String.format(MODULE_WITH_PROPERTIES, ruleClassname, formatProperties(rule.getProperties())); } - private String getLowerCaseRuleName() { - return getName().toLowerCase(LOCALE); + /** + * Checks that this rule comes from the source named. + * + * @param sourceName the name of the source to check against + * @return true if this rule comes from the source + */ + public boolean isFromSource(final String sourceName) { + return getSource() + .equals(sourceName); + } + + /** + * The name of the source for the rule. + * + * @return the source name, in lowercase. + */ + public String getSource() { + return source.toLowerCase(Locale.ENGLISH); } } diff --git a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/RuleLoader.java b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/RuleLoader.java new file mode 100644 index 0000000..b458e9c --- /dev/null +++ b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/RuleLoader.java @@ -0,0 +1,63 @@ +package net.kemitix.checkstyle.ruleset.builder; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.function.Predicate; +import java.util.stream.Collectors; + +@Component +@RequiredArgsConstructor +public class RuleLoader { + + private static final String NEWLINE = "\n"; + + private final RulesProperties rulesProperties; + private final RuleReadmeLoader ruleReadmeLoader; + private final SourcesProperties sourcesProperties; + + /** + * Loads from the source, where the source is enabled, all rules that are + * themselves enabled. + * + * @param sourceName the source to load from + * @return a formatted string containing the enabled rules. + */ + public String loadEnabled(final String sourceName) { + if (!isEnabledRuleSource(sourceName)) { + return ""; + } + return readmeRules(rule -> + rule.isFromSource(sourceName) + && rule.isEnabled()); + } + + /** + * Loads from the source, where either the source is disabled or the rule + * is itself disabled. + * + * @param sourceName the source to load from + * @return a formatted string containing the disabled rules. + */ + public String loadDisabled(final String sourceName) { + boolean enabledRuleSource = isEnabledRuleSource(sourceName); + return readmeRules(rule -> + rule.isFromSource(sourceName) + && (!enabledRuleSource || !rule.isEnabled())); + } + + private boolean isEnabledRuleSource(final String sourceName) { + return sourcesProperties.getSources().stream() + .filter(RuleSource::isEnabled) + .map(RuleSource::getName) + .anyMatch(sourceName::equals); + } + + private String readmeRules(final Predicate predicate) { + return rulesProperties.getRules().stream() + .filter(predicate) + .sorted(Rule::sortByName) + .flatMap(ruleReadmeLoader::load) + .collect(Collectors.joining(NEWLINE)); + } +} diff --git a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/RuleSource.java b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/RuleSource.java index 9aba51d..7ebc2ed 100644 --- a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/RuleSource.java +++ b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/RuleSource.java @@ -1,27 +1,21 @@ package net.kemitix.checkstyle.ruleset.builder; import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; /** * The origin of the rule. * * @author Paul Campbell (pcampbell@kemitix.net) */ -public enum RuleSource { +@Setter +@Getter +@NoArgsConstructor +public class RuleSource { - CHECKSTYLE("com.puppycrawl.tools.checkstyle"), - SEVNTU("com.github.sevntu.checkstyle.checks"); + private String name; + private boolean enabled; + private String basePackage; - @Getter - private final String basePackage; - - - /** - * Constructor. - * - * @param basePackage the base package that contains all checks from this source - */ - RuleSource(final String basePackage) { - this.basePackage = basePackage; - } } diff --git a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/SourcesProperties.java b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/SourcesProperties.java new file mode 100644 index 0000000..eaf962b --- /dev/null +++ b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/SourcesProperties.java @@ -0,0 +1,30 @@ +package net.kemitix.checkstyle.ruleset.builder; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +/** + * Properties defining the sources. + * + * @author Paul Campbell (pcampbell@kemitix.net) + */ +@Setter +@Getter +@Configuration +@ConfigurationProperties +class SourcesProperties { + + private List sources = new ArrayList<>(); + + public Optional findSource(final String sourceName) { + return sources.stream() + .filter(ruleSource -> ruleSource.getName().equals(sourceName)) + .findFirst(); + } +} diff --git a/builder/src/main/resources/application.yml b/builder/src/main/resources/application.yml index 773da5c..810853b 100644 --- a/builder/src/main/resources/application.yml +++ b/builder/src/main/resources/application.yml @@ -12,6 +12,15 @@ template: checkstyle-xml: builder/src/main/resources/checkstyle-template.xml readme-template: builder/src/main/resources/README-template.md readme-fragments: builder/src/main/resources/rules +sources: + - + name: checkstyle + enabled: true + base-package: com.puppycrawl.tools.checkstyle + - + name: sevntu + enabled: false + base-package: com.github.sevntu.checkstyle.checks rules: - name: RegexpOnFilename @@ -495,7 +504,7 @@ rules: uri: http://checkstyle.sourceforge.net/config_blocks.html#LeftCurly - name: LineLength - parent: TREEWALKER + parent: CHECKER level: LAYOUT enabled: true source: CHECKSTYLE diff --git a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/BuilderConfigurationTest.java b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/BuilderConfigurationTest.java index f9afaa8..59ee2e2 100644 --- a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/BuilderConfigurationTest.java +++ b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/BuilderConfigurationTest.java @@ -4,6 +4,7 @@ import com.google.common.reflect.ClassPath; import org.junit.Test; import java.io.IOException; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -21,20 +22,26 @@ import static org.mockito.Mockito.mock; */ public class BuilderConfigurationTest { + private SourcesProperties sourceProperties = new SourcesProperties(); + @Test public void canGetCheckClasses() { //given final PackageScanner packageScanner = mock(PackageScanner.class); final String checkstyleClass = "checkstyle class"; - given(packageScanner.apply(RuleSource.CHECKSTYLE)).willReturn(singletonList(checkstyleClass)); + final RuleSource checkstyleRuleSource = RuleSourceMother.checkstyle.get(); + final RuleSource sevntuRuleSource = RuleSourceMother.sevntu.get(); + given(packageScanner.apply(checkstyleRuleSource)).willReturn(singletonList(checkstyleClass)); final String sevntuClass = "sevntu class"; - given(packageScanner.apply(RuleSource.SEVNTU)).willReturn(singletonList(sevntuClass)); + given(packageScanner.apply(sevntuRuleSource)).willReturn(singletonList(sevntuClass)); + sourceProperties.setSources(Arrays.asList(checkstyleRuleSource, sevntuRuleSource)); + BuilderConfiguration subject = new BuilderConfiguration(sourceProperties); //when - final Map> checkClasses = new BuilderConfiguration().checkClasses(packageScanner); + final Map> checkClasses = subject.checkClasses(packageScanner); //then - assertThat(checkClasses).containsOnlyKeys(RuleSource.values()); + assertThat(checkClasses).containsOnlyKeys(Arrays.asList(checkstyleRuleSource, sevntuRuleSource)); assertThat(checkClasses) - .containsEntry(RuleSource.CHECKSTYLE, singletonList(checkstyleClass)) - .containsEntry(RuleSource.SEVNTU, singletonList(sevntuClass)); + .containsEntry(checkstyleRuleSource, singletonList(checkstyleClass)) + .containsEntry(sevntuRuleSource, singletonList(sevntuClass)); } } diff --git a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleWriterTest.java b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleWriterTest.java index d8afa45..0eab043 100644 --- a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleWriterTest.java +++ b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleWriterTest.java @@ -15,6 +15,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.AbstractMap; +import java.util.Arrays; import java.util.List; import java.util.Map; @@ -58,6 +59,7 @@ public class CheckstyleWriterTest { private Path outputDirectory; private RuleClassLocator ruleClassLocator = mock(RuleClassLocator.class); + private SourcesProperties sourceProperties = new SourcesProperties(); @Before public void setUp() throws Exception { @@ -82,8 +84,18 @@ public class CheckstyleWriterTest { checkstyleTemplate, TEMPLATE.getBytes(StandardCharsets.UTF_8), StandardOpenOption.TRUNCATE_EXISTING); templateProperties.setCheckstyleXml(checkstyleTemplate); rulesProperties = new RulesProperties(); + sourceProperties.setSources(Arrays.asList( + RuleSourceMother.checkstyle.get(), + RuleSourceMother.sevntu.get() + )); checkstyleWriter = - new CheckstyleWriter(outputProperties, templateProperties, rulesProperties, ruleClassLocator); + new CheckstyleWriter( + outputProperties, + templateProperties, + rulesProperties, + ruleClassLocator, + sourceProperties); + checkstyleWriter.init(); given(ruleClassLocator.apply(any())).willReturn(ruleClassname); } @@ -116,7 +128,7 @@ public class CheckstyleWriterTest { private Rule enabledRule(final RuleLevel level, final RuleParent parent) { val rule = new Rule(); rule.setName(ruleName); - rule.setSource(RuleSource.CHECKSTYLE); + rule.setSource(RuleSourceMother.checkstyle.get().getName()); rule.setEnabled(true); rule.setLevel(level); rule.setParent(parent); diff --git a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/ClassGraphPackageScannerTest.java b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/ClassGraphPackageScannerTest.java index c7ff4d8..2197293 100644 --- a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/ClassGraphPackageScannerTest.java +++ b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/ClassGraphPackageScannerTest.java @@ -15,21 +15,25 @@ public class ClassGraphPackageScannerTest { private PackageScanner scanner = new ClassGraphPackageScanner(); + private final RuleSource checkstyleRuleSource = RuleSourceMother.checkstyle.get(); + + private final RuleSource sevntuRuleSource = RuleSourceMother.sevntu.get(); + @Test public void canScanCheckstylePackage() { //when - final List result = scanner.apply(RuleSource.CHECKSTYLE); + final List result = scanner.apply(checkstyleRuleSource); //then - assertThat(result).allMatch(cn -> cn.startsWith(RuleSource.CHECKSTYLE.getBasePackage())) + assertThat(result).allMatch(cn -> cn.startsWith(checkstyleRuleSource.getBasePackage())) .contains("com.puppycrawl.tools.checkstyle.checks.sizes.FileLengthCheck"); } @Test public void canScanSevntuPackage() { //when - final List result = scanner.apply(RuleSource.SEVNTU); + final List result = scanner.apply(sevntuRuleSource); //then - assertThat(result).allMatch(cn -> cn.startsWith(RuleSource.SEVNTU.getBasePackage())) + assertThat(result).allMatch(cn -> cn.startsWith(sevntuRuleSource.getBasePackage())) .contains("com.github.sevntu.checkstyle.checks.design.NestedSwitchCheck"); } } diff --git a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/DefaultReadmeIndexBuilderTest.java b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/DefaultReadmeIndexBuilderTest.java index 535fb4d..1356f34 100644 --- a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/DefaultReadmeIndexBuilderTest.java +++ b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/DefaultReadmeIndexBuilderTest.java @@ -37,12 +37,14 @@ public class DefaultReadmeIndexBuilderTest { expectedIndexItems.add("[e](#e)|complexity|checkstyle|Yes|"); expectedIndexItems.add("[f](#f)|unspecified|checkstyle|Yes|"); val rules = rulesProperties.getRules(); - rules.add(rule("a", RuleLevel.LAYOUT, RuleSource.CHECKSTYLE, true, true)); - rules.add(rule("b", RuleLevel.NAMING, RuleSource.SEVNTU, false, false)); - rules.add(rule("c", RuleLevel.JAVADOC, RuleSource.CHECKSTYLE, true, true)); - rules.add(rule("d", RuleLevel.TWEAKS, RuleSource.CHECKSTYLE, true, true)); - rules.add(rule("e", RuleLevel.COMPLEXITY, RuleSource.CHECKSTYLE, true, true)); - rules.add(rule("f", RuleLevel.UNSPECIFIED, RuleSource.CHECKSTYLE, true, true)); + RuleSource checkStyleRuleSource = RuleSourceMother.checkstyle.get(); + RuleSource sevntuRuleSource = RuleSourceMother.sevntu.get(); + rules.add(rule("a", RuleLevel.LAYOUT, checkStyleRuleSource, true, true)); + rules.add(rule("b", RuleLevel.NAMING, sevntuRuleSource, false, false)); + rules.add(rule("c", RuleLevel.JAVADOC, checkStyleRuleSource, true, true)); + rules.add(rule("d", RuleLevel.TWEAKS, checkStyleRuleSource, true, true)); + rules.add(rule("e", RuleLevel.COMPLEXITY, checkStyleRuleSource, true, true)); + rules.add(rule("f", RuleLevel.UNSPECIFIED, checkStyleRuleSource, true, true)); //when val index = indexBuilder.build() .split("\n"); @@ -57,7 +59,7 @@ public class DefaultReadmeIndexBuilderTest { val rule = new Rule(); rule.setName(name); rule.setLevel(level); - rule.setSource(source); + rule.setSource(source.getName()); rule.setEnabled(enabled); rule.setInsuppressible(!supressible); return rule; diff --git a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/DefaultRuleClassLocatorTest.java b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/DefaultRuleClassLocatorTest.java index 3e9dd11..4715f9f 100644 --- a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/DefaultRuleClassLocatorTest.java +++ b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/DefaultRuleClassLocatorTest.java @@ -1,11 +1,9 @@ package net.kemitix.checkstyle.ruleset.builder; +import org.junit.Before; import org.junit.Test; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -19,7 +17,22 @@ public class DefaultRuleClassLocatorTest { private final Map> checkClasses = new HashMap<>(); - private final DefaultRuleClassLocator subject = new DefaultRuleClassLocator(checkClasses); + private SourcesProperties sourceProperties = new SourcesProperties(); + + private final DefaultRuleClassLocator subject = + new DefaultRuleClassLocator( + checkClasses, + sourceProperties); + + private final RuleSource checkstyleRuleSource = RuleSourceMother.checkstyle.get(); + private final RuleSource sevntuRuleSource = RuleSourceMother.sevntu.get(); + + @Before + public void setUp() { + sourceProperties.setSources(Arrays.asList( + checkstyleRuleSource, sevntuRuleSource + )); + } @Test public void canLookupRuleWithClassNameEndingInCheck() { @@ -28,8 +41,8 @@ public class DefaultRuleClassLocatorTest { final String expected = "com.puppycrawl.tools.checkstyle.checks.regexp.RegexpOnFilenameCheck"; final List checkstyleClasses = Collections.singletonList(expected); final List sevntuClasses = Collections.emptyList(); - checkClasses.put(RuleSource.CHECKSTYLE, checkstyleClasses); - checkClasses.put(RuleSource.SEVNTU, sevntuClasses); + checkClasses.put(checkstyleRuleSource, checkstyleClasses); + checkClasses.put(sevntuRuleSource, sevntuClasses); final Rule rule = createCheckstyleRule(rulename); //when final String result = subject.apply(rule); @@ -44,8 +57,8 @@ public class DefaultRuleClassLocatorTest { final String expected = "com.puppycrawl.tools.checkstyle.checks.regexp.RegexpOnFilename"; final List checkstyleClasses = Collections.singletonList(expected); final List sevntuClasses = Collections.emptyList(); - checkClasses.put(RuleSource.CHECKSTYLE, checkstyleClasses); - checkClasses.put(RuleSource.SEVNTU, sevntuClasses); + checkClasses.put(checkstyleRuleSource, checkstyleClasses); + checkClasses.put(sevntuRuleSource, sevntuClasses); final Rule rule = createCheckstyleRule(rulename); //when final String result = subject.apply(rule); @@ -60,8 +73,8 @@ public class DefaultRuleClassLocatorTest { final String expected = "com.puppycrawl.tools.checkstyle.checks.regexp.RegexpOnFilenameNoMatch"; final List checkstyleClasses = Collections.singletonList(expected); final List sevntuClasses = Collections.emptyList(); - checkClasses.put(RuleSource.CHECKSTYLE, checkstyleClasses); - checkClasses.put(RuleSource.SEVNTU, sevntuClasses); + checkClasses.put(checkstyleRuleSource, checkstyleClasses); + checkClasses.put(sevntuRuleSource, sevntuClasses); final Rule rule = createCheckstyleRule(rulename); //then assertThatThrownBy(() -> subject.apply(rule)) @@ -71,7 +84,7 @@ public class DefaultRuleClassLocatorTest { private Rule createCheckstyleRule(final String rulename) { final Rule rule = new Rule(); - rule.setSource(RuleSource.CHECKSTYLE); + rule.setSource(checkstyleRuleSource.getName()); rule.setName(rulename); return rule; } diff --git a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/FileWriterReaderTest.java b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/FileWriterReaderTest.java new file mode 100644 index 0000000..ad85ea4 --- /dev/null +++ b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/FileWriterReaderTest.java @@ -0,0 +1,41 @@ +package net.kemitix.checkstyle.ruleset.builder; + +import org.junit.Before; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; + +public class FileWriterReaderTest { + + + private String line1 = UUID.randomUUID().toString(); + private String line2 = UUID.randomUUID().toString(); + private String body = line1 + "\n" + line2; + + @org.junit.Rule + public TemporaryFolder folder = new TemporaryFolder(); + + private Path path; + + private FileWriter writer = new FileWriter(); + private FileReader reader = new FileReader(); + + @Before + public void setUp() throws IOException { + path = folder.newFile().toPath(); + } + + @Test + public void writeTheReadFile() throws IOException { + //when + writer.write(path, body); + String read = reader.read(path); + //then + assertThat(read).isEqualTo(body); + } +} \ No newline at end of file diff --git a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/ReadmeBuilderTest.java b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/ReadmeBuilderTest.java new file mode 100644 index 0000000..68d4f2c --- /dev/null +++ b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/ReadmeBuilderTest.java @@ -0,0 +1,48 @@ +package net.kemitix.checkstyle.ruleset.builder; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; + +public class ReadmeBuilderTest { + + @Mock + private ReadmeIndexBuilder indexBuilder; + @Mock + private RuleLoader ruleLoader; + private ReadmeBuilder readmeBuilder; + private String template = "i:%s,ec:%s,es:%s,dc:%s,ds:%s"; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + readmeBuilder = new ReadmeBuilder(indexBuilder, ruleLoader); + } + + @Test + public void canBuild() { + //given + given(indexBuilder.build()).willReturn("index"); + given(ruleLoader.loadEnabled("checkstyle")).willReturn("enabled-checkstyle"); + given(ruleLoader.loadEnabled("sevntu")).willReturn("enabled-sevntu"); + given(ruleLoader.loadDisabled("checkstyle")).willReturn("disabled-checkstyle"); + given(ruleLoader.loadDisabled("sevntu")).willReturn("disabled-sevntu"); + //when + String result = readmeBuilder.build(template); + //then + assertThat(result).isEqualTo( + "i:index," + + "ec:enabled-checkstyle," + + "es:enabled-sevntu," + + "dc:disabled-checkstyle," + + "ds:disabled-sevntu"); + } + +} \ No newline at end of file diff --git a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/ReadmeWriterTest.java b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/ReadmeWriterTest.java index 51ad769..354fda9 100644 --- a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/ReadmeWriterTest.java +++ b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/ReadmeWriterTest.java @@ -2,19 +2,26 @@ package net.kemitix.checkstyle.ruleset.builder; import lombok.val; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.rules.TemporaryFolder; +import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.io.File; +import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; +import java.util.UUID; +import java.util.function.Supplier; import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.verify; /** * Tests for {@link ReadmeWriter}. @@ -23,95 +30,50 @@ import static org.mockito.BDDMockito.given; */ public class ReadmeWriterTest { + @Mock + private ReadmeBuilder readmeBuilder; + + private TemplateProperties templateProperties = new TemplateProperties(); + private OutputProperties outputProperties = new OutputProperties(); + + @Mock + private FileReader fileReader; + + @Mock + private FileWriter fileWriter; + + @InjectMocks private ReadmeWriter readmeWriter; - private RulesProperties rulesProperties; - @Mock - private RuleReadmeLoader ruleReadmeLoader; - + private Path templatePath; @Mock - private ReadmeIndexBuilder indexBuilder; - - private Path readme; - - @org.junit.Rule - public TemporaryFolder folder = new TemporaryFolder(); + private Path outputPath; + private String templateBody = UUID.randomUUID().toString(); + private String formattedOutput = UUID.randomUUID().toString(); @Before - public void setUp() throws Exception { + public void setUp() throws IOException { MockitoAnnotations.initMocks(this); - final Path template = folder.newFile("README-template.md") - .toPath(); - Files.write(template, Arrays.asList("i:%s", "ce:%s", "se:%s", "cd:%s", "sd:%s")); - final TemplateProperties templateProperties = new TemplateProperties(); - templateProperties.setReadmeTemplate(template); - final Path fragments = folder.newFolder("fragments") - .toPath(); - templateProperties.setReadmeFragments(fragments); - final OutputProperties outputProperties = new OutputProperties(); - readme = folder.newFile("README.md") - .toPath(); - outputProperties.setReadme(readme); - rulesProperties = new RulesProperties(); + readmeWriter = - new ReadmeWriter(templateProperties, outputProperties, rulesProperties, ruleReadmeLoader, indexBuilder); + new ReadmeWriter(templateProperties, outputProperties, + readmeBuilder, fileReader, fileWriter); + + templateProperties.setReadmeTemplate(templatePath); + outputProperties.setReadme(outputPath); + given(fileReader.read(templatePath)) + .willReturn(templateBody); + given(readmeBuilder.build(templateBody)) + .willReturn(formattedOutput); } @Test - public void createReadme() throws Exception { - //given - val expected = Arrays.asList("i:index", "ce:checkstyle-enabled", "se:sevntu-enabled", "cd:checkstyle-disabled", - "sd:sevntu-disabled" - ); - val rules = rulesProperties.getRules(); - final Rule checkstyleEnabled = rule(RuleSource.CHECKSTYLE, true, "checkstyle enabled"); - final Rule checkstyleDisabled = rule(RuleSource.CHECKSTYLE, false, "checkstyle disabled"); - final Rule sevntuEnabled = rule(RuleSource.SEVNTU, true, "sevntu enabled"); - final Rule sevntuDisabled = rule(RuleSource.SEVNTU, false, "sevntu disabled"); - rules.add(checkstyleEnabled); - rules.add(checkstyleDisabled); - rules.add(sevntuEnabled); - rules.add(sevntuDisabled); - given(indexBuilder.build()).willReturn("index"); - given(ruleReadmeLoader.load(checkstyleEnabled)).willReturn(Stream.of("checkstyle-enabled")); - given(ruleReadmeLoader.load(checkstyleDisabled)).willReturn(Stream.of("checkstyle-disabled")); - given(ruleReadmeLoader.load(sevntuEnabled)).willReturn(Stream.of("sevntu-enabled")); - given(ruleReadmeLoader.load(sevntuDisabled)).willReturn(Stream.of("sevntu-disabled")); + public void readAndWrite() throws Exception { //when readmeWriter.run(); //then - final Stream lines = Files.lines(readme, StandardCharsets.UTF_8); - assertThat(lines).containsExactlyElementsOf(expected); + verify(fileWriter).write(outputPath, formattedOutput); } - private Rule rule(final RuleSource source, final boolean enabled, final String name) { - val rule = new Rule(); - rule.setName(name); - rule.setSource(source); - rule.setEnabled(enabled); - return rule; - } - - @Test - public void rulesAreAlphabetical() throws Exception { - //given - val expected = Arrays.asList("ce:alpha", "beta", "delta"); - val rules = rulesProperties.getRules(); - final Rule alpha = rule(RuleSource.CHECKSTYLE, true, "alpha"); - final Rule beta = rule(RuleSource.CHECKSTYLE, true, "beta"); - final Rule delta = rule(RuleSource.CHECKSTYLE, true, "delta"); - rules.add(alpha); - rules.add(delta); - rules.add(beta); - given(indexBuilder.build()).willReturn("index"); - given(ruleReadmeLoader.load(alpha)).willReturn(Stream.of(alpha.getName())); - given(ruleReadmeLoader.load(beta)).willReturn(Stream.of(beta.getName())); - given(ruleReadmeLoader.load(delta)).willReturn(Stream.of(delta.getName())); - //when - readmeWriter.run(); - //then - final Stream lines = Files.lines(readme, StandardCharsets.UTF_8); - assertThat(lines).containsSequence(expected); - } } diff --git a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/RuleLoaderTest.java b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/RuleLoaderTest.java new file mode 100644 index 0000000..4afeb7e --- /dev/null +++ b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/RuleLoaderTest.java @@ -0,0 +1,130 @@ +package net.kemitix.checkstyle.ruleset.builder; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; + +public class RuleLoaderTest { + + private RulesProperties ruleProperties = new RulesProperties(); + @Mock + private RuleReadmeLoader ruleReadmeLoader; + private SourcesProperties sourcesProperties = new SourcesProperties(); + private RuleLoader ruleLoader; + List ruleSources = sourcesProperties.getSources(); + private List rules = ruleProperties.getRules(); + private RuleSource enabledRuleSource; + private String enabledRuleSourceName = "enabled-" + UUID.randomUUID().toString(); + private String enabledRuleSourcePackage = "enabled-" + UUID.randomUUID().toString(); + private RuleSource disabledRuleSource; + private String disabledRuleSourceName = "disabled-" + UUID.randomUUID().toString(); + private String disabledRuleSourcePackage = "disabled-" + UUID.randomUUID().toString(); + private Rule enabledRule = new Rule(); + private List enabledRuleLines = new ArrayList<>(); + private String enabledRuleLineOne = "enabled-1-" + UUID.randomUUID().toString(); + private String enabledRuleLineTwo = "enabled-2-" + UUID.randomUUID().toString(); + private String enabledRuleFormatted = + enabledRuleLineOne + "\n" + + enabledRuleLineTwo; + private Rule disabledRule = new Rule(); + private List disabledRuleLines = new ArrayList<>(); + private String disabledRuleLineOne = "disabled-1-" + UUID.randomUUID().toString(); + private String disabledRuleLineTwo = "disabled-2-" + UUID.randomUUID().toString(); + private String disabledRuleFormatted = + disabledRuleLineOne + "\n" + + disabledRuleLineTwo; + private String enabledRuleName = "enabled-" + UUID.randomUUID().toString(); + private String disabledRuleName = "disabled-" + UUID.randomUUID().toString(); + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + ruleLoader = + new RuleLoader( + ruleProperties, + ruleReadmeLoader, + sourcesProperties); + + enabledRule.setEnabled(true); + enabledRule.setName(enabledRuleName); + + disabledRule.setEnabled(false); + disabledRule.setName(disabledRuleName); + + enabledRuleSource = RuleSourceMother.create( + enabledRuleSourceName, + true, + enabledRuleSourcePackage); + ruleSources.add(enabledRuleSource); + rules.add(enabledRule); + enabledRuleLines.add(enabledRuleLineOne); + enabledRuleLines.add(enabledRuleLineTwo); + given(ruleReadmeLoader.load(enabledRule)) + .willReturn(enabledRuleLines.stream()); + + disabledRuleSource = RuleSourceMother.create( + disabledRuleSourceName, + false, + disabledRuleSourcePackage); + ruleSources.add(disabledRuleSource); + rules.add(disabledRule); + disabledRuleLines.add(disabledRuleLineOne); + disabledRuleLines.add(disabledRuleLineTwo); + given(ruleReadmeLoader.load(disabledRule)) + .willReturn(disabledRuleLines.stream()); + } + + @Test + public void enabledForEnabledSource() { + //given + enabledRule.setSource(enabledRuleSourceName); + disabledRule.setSource(enabledRuleSourceName); + //when + String result = ruleLoader.loadEnabled(enabledRuleSourceName); + //then + assertThat(result).contains(enabledRuleFormatted); + } + + @Test + public void enabledForDisabledSource() { + //given + enabledRule.setSource(disabledRuleSourceName); + disabledRule.setSource(disabledRuleSourceName); + //when + String result = ruleLoader.loadEnabled(disabledRuleSourceName); + //then + assertThat(result).isEmpty(); + } + @Test + public void disabledForEnabledSource() { + //given + enabledRule.setSource(enabledRuleSourceName); + disabledRule.setSource(enabledRuleSourceName); + //when + String result = ruleLoader.loadDisabled(enabledRuleSourceName); + //then + assertThat(result).contains(disabledRuleFormatted); + } + + @Test + public void disabledForDisabledSource() { + //given + enabledRule.setSource(disabledRuleSourceName); + disabledRule.setSource(disabledRuleSourceName); + //when + String result = ruleLoader.loadDisabled(disabledRuleSourceName); + //then + assertThat(result) + .contains(enabledRuleFormatted) + .contains(disabledRuleFormatted); + } +} diff --git a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/RuleSourceMother.java b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/RuleSourceMother.java new file mode 100644 index 0000000..8c41ef9 --- /dev/null +++ b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/RuleSourceMother.java @@ -0,0 +1,34 @@ +package net.kemitix.checkstyle.ruleset.builder; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Supplier; + +public class RuleSourceMother { + + public static Supplier checkstyle = () -> + RuleSourceMother.create( + "checkstyle", + true, + "com.puppycrawl.tools.checkstyle"); + + public static Supplier sevntu = () -> + RuleSourceMother.create( + "sevntu", + true, + "com.github.sevntu.checkstyle.checks"); + + public static Supplier> list = () -> + Arrays.asList( + checkstyle.get(), + sevntu.get() + ); + + public static RuleSource create(String name, boolean enabled, String basePackage) { + RuleSource ruleSource = new RuleSource(); + ruleSource.setName(name); + ruleSource.setEnabled(enabled); + ruleSource.setBasePackage(basePackage); + return ruleSource; + } +} diff --git a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/RuleSourceTest.java b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/RuleSourceTest.java index 47397a4..4c0df94 100644 --- a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/RuleSourceTest.java +++ b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/RuleSourceTest.java @@ -1,9 +1,9 @@ package net.kemitix.checkstyle.ruleset.builder; -import lombok.val; import org.junit.Test; -import java.util.Arrays; +import java.util.Random; +import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; @@ -14,32 +14,18 @@ import static org.assertj.core.api.Assertions.assertThat; */ public class RuleSourceTest { - @Test - public void valueOf() throws Exception { - assertThat(RuleSource.valueOf("CHECKSTYLE")).isEqualTo(RuleSource.CHECKSTYLE); - assertThat(RuleSource.valueOf("SEVNTU")).isEqualTo(RuleSource.SEVNTU); - } + private String name = UUID.randomUUID().toString(); + private String basePackage = UUID.randomUUID().toString(); + private boolean enabled = new Random().nextBoolean(); @Test - public void values() throws Exception { + public void create() { //given - val expected = Arrays.asList("CHECKSTYLE", "SEVNTU"); - //when - val values = Arrays.stream(RuleSource.values()) - .map(RuleSource::toString); + RuleSource ruleSource = RuleSourceMother.create(name, enabled, basePackage); //then - assertThat(values).containsExactlyElementsOf(expected); + assertThat(ruleSource.getName()).isEqualTo(name); + assertThat(ruleSource.getBasePackage()).isEqualTo(basePackage); + assertThat(ruleSource.isEnabled()).isEqualTo(enabled); } - @Test - public void basePackages() { - //given - final String puppycrawl = "puppycrawl"; - final String sevntu = "sevntu"; - //then - assertThat(RuleSource.CHECKSTYLE.getBasePackage()).contains(puppycrawl) - .doesNotContain(sevntu); - assertThat(RuleSource.SEVNTU.getBasePackage()).contains(sevntu) - .doesNotContain(puppycrawl); - } } diff --git a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/RuleTest.java b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/RuleTest.java index 8dd535c..92241b6 100644 --- a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/RuleTest.java +++ b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/RuleTest.java @@ -4,6 +4,7 @@ import lombok.val; import org.assertj.core.api.SoftAssertions; import org.junit.Before; import org.junit.Test; +import org.mockito.Mock; import java.net.URI; @@ -16,6 +17,8 @@ public class RuleTest { private Rule rule; + private RuleSource ruleSource = RuleSourceMother.checkstyle.get(); + @Before public void setUp() throws Exception { rule = new Rule(); @@ -27,7 +30,6 @@ public class RuleTest { val name = "name"; val parent = RuleParent.TREEWALKER; val level = RuleLevel.LAYOUT; - val source = RuleSource.CHECKSTYLE; val enabled = true; val insuppressible = true; val uri = URI.create("rule://name.md"); @@ -38,7 +40,7 @@ public class RuleTest { rule.setName(name); rule.setParent(parent); rule.setLevel(level); - rule.setSource(source); + rule.setSource(ruleSource.getName()); rule.setEnabled(enabled); rule.setInsuppressible(insuppressible); rule.setUri(uri); @@ -58,7 +60,7 @@ public class RuleTest { .isEqualTo(level); softly.assertThat(rule.getSource()) .as("set/getSource()") - .isEqualTo(source); + .isEqualTo(ruleSource.getName()); softly.assertThat(rule.isEnabled()) .as("set/isEnabled()") .isEqualTo(enabled); diff --git a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/SourcesPropertiesTest.java b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/SourcesPropertiesTest.java new file mode 100644 index 0000000..b403591 --- /dev/null +++ b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/SourcesPropertiesTest.java @@ -0,0 +1,31 @@ +package net.kemitix.checkstyle.ruleset.builder; + +import org.junit.Before; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class SourcesPropertiesTest { + + private SourcesProperties sourcesProperties; + + @Before + public void setUp() { + sourcesProperties = new SourcesProperties(); + } + + @Test + public void getEmpty() { + assertThat(sourcesProperties.getSources()).isEmpty(); + } + @Test + public void getContent() { + //given + final RuleSource source = + RuleSourceMother.create("name", true, "package"); + //when + sourcesProperties.getSources().add(source); + //then + assertThat(sourcesProperties.getSources()).containsExactly(source); + } +} diff --git a/ruleset/src/main/resources/net/kemitix/checkstyle-1-layout.xml b/ruleset/src/main/resources/net/kemitix/checkstyle-1-layout.xml index 354e0a0..94b2a1c 100644 --- a/ruleset/src/main/resources/net/kemitix/checkstyle-1-layout.xml +++ b/ruleset/src/main/resources/net/kemitix/checkstyle-1-layout.xml @@ -9,6 +9,9 @@ + + + @@ -25,9 +28,6 @@ - - - @@ -52,8 +52,6 @@ - - diff --git a/ruleset/src/main/resources/net/kemitix/checkstyle-2-naming.xml b/ruleset/src/main/resources/net/kemitix/checkstyle-2-naming.xml index eed5a01..2436f67 100644 --- a/ruleset/src/main/resources/net/kemitix/checkstyle-2-naming.xml +++ b/ruleset/src/main/resources/net/kemitix/checkstyle-2-naming.xml @@ -9,6 +9,9 @@ + + + @@ -32,9 +35,6 @@ - - - @@ -79,12 +79,6 @@ - - - - - - diff --git a/ruleset/src/main/resources/net/kemitix/checkstyle-3-javadoc.xml b/ruleset/src/main/resources/net/kemitix/checkstyle-3-javadoc.xml index 0f6111a..2215de3 100644 --- a/ruleset/src/main/resources/net/kemitix/checkstyle-3-javadoc.xml +++ b/ruleset/src/main/resources/net/kemitix/checkstyle-3-javadoc.xml @@ -10,6 +10,9 @@ + + + @@ -42,9 +45,6 @@ - - - @@ -98,12 +98,6 @@ - - - - - - diff --git a/ruleset/src/main/resources/net/kemitix/checkstyle-4-tweaks.xml b/ruleset/src/main/resources/net/kemitix/checkstyle-4-tweaks.xml index 31de4f1..9bcaea8 100644 --- a/ruleset/src/main/resources/net/kemitix/checkstyle-4-tweaks.xml +++ b/ruleset/src/main/resources/net/kemitix/checkstyle-4-tweaks.xml @@ -10,6 +10,9 @@ + + + @@ -70,9 +73,6 @@ - - - @@ -142,32 +142,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ruleset/src/main/resources/net/kemitix/checkstyle-5-complexity.xml b/ruleset/src/main/resources/net/kemitix/checkstyle-5-complexity.xml index 87123f9..81575db 100644 --- a/ruleset/src/main/resources/net/kemitix/checkstyle-5-complexity.xml +++ b/ruleset/src/main/resources/net/kemitix/checkstyle-5-complexity.xml @@ -13,6 +13,9 @@ + + + @@ -95,9 +98,6 @@ - - - @@ -188,38 +188,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -