diff --git a/.github/workflows/bld.yml b/.github/workflows/bld.yml index 2b0ba38..6966bcb 100644 --- a/.github/workflows/bld.yml +++ b/.github/workflows/bld.yml @@ -4,29 +4,36 @@ on: [ push, pull_request, workflow_dispatch ] jobs: build-bld-project: - runs-on: ubuntu-latest - strategy: matrix: - java-version: [ 17, 20 ] + java-version: [ 17, 21, 24 ] + kotlin-version: [ 1.9.25, 2.0.21, 2.1.20 ] + os: [ ubuntu-latest, windows-latest, macos-latest ] + + runs-on: ${{ matrix.os }} steps: - name: Checkout source repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up JDK ${{ matrix.java-version }} - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: - distribution: 'zulu' + distribution: "zulu" java-version: ${{ matrix.java-version }} - - name: Grant execute permission for bld - run: chmod +x bld - - - name: Download the dependencies + - name: Download dependencies [examples] + working-directory: examples run: ./bld download - - name: Run tests with bld - run: ./bld compile test + - name: Compile and Run Checkstyle [examples] + working-directory: examples + run: ./bld compile checkstyle-custom + + - name: Download dependencies + run: ./bld download + + - name: Run tests + run: ./bld compile test \ No newline at end of file diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index e69de29..508f6a5 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -0,0 +1,57 @@ +name: javadocs-pages + +on: + # Runs on pushes targeting the default branch + push: + branches: ["master"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow one concurrent deployment +concurrency: + group: "pages" + cancel-in-progress: true + +jobs: + # Single deploy job since we're just deploying + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + + runs-on: ubuntu-latest + + steps: + - name: Checkout source repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + distribution: "zulu" + java-version: 17 + + - name: Build Javadocs + run: ./bld download clean javadoc + + - name: Setup Pages + uses: actions/configure-pages@v3 + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + # Upload generated Javadocs repository + path: "build/javadoc/" + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.idea/bld.xml b/.idea/bld.xml new file mode 100644 index 0000000..6600cee --- /dev/null +++ b/.idea/bld.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..d91f848 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/copyright/Apache_License.xml b/.idea/copyright/Apache_License.xml index 15687f4..4446c15 100644 --- a/.idea/copyright/Apache_License.xml +++ b/.idea/copyright/Apache_License.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/.idea/icon.svg b/.idea/icon.svg new file mode 100644 index 0000000..81220b4 --- /dev/null +++ b/.idea/icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.idea/intellij-javadocs-4.0.1.xml b/.idea/intellij-javadocs-4.0.1.xml new file mode 100644 index 0000000..90d3347 --- /dev/null +++ b/.idea/intellij-javadocs-4.0.1.xml @@ -0,0 +1,204 @@ + + + + + UPDATE + false + true + + FIELD + METHOD + TYPE + + + PUBLIC + PROTECTED + DEFAULT + + + + + + ^.*(public|protected|private)*.+interface\s+\w+.* + /**\n + * The interface ${name}.\n +<#if element.typeParameters?has_content> * \n +</#if> +<#list element.typeParameters as typeParameter> + * @param <${typeParameter.name}> the type parameter\n +</#list> + */ + + + ^.*(public|protected|private)*.+enum\s+\w+.* + /**\n + * The enum ${name}.\n + */ + + + ^.*(public|protected|private)*.+class\s+\w+.* + /**\n + * The type ${name}.\n +<#if element.typeParameters?has_content> * \n +</#if> +<#list element.typeParameters as typeParameter> + * @param <${typeParameter.name}> the type parameter\n +</#list> + */ + + + .+ + /**\n + * The type ${name}.\n + */ + + + + + .+ + /**\n + * Instantiates a new ${name}.\n +<#if element.parameterList.parameters?has_content> + *\n +</#if> +<#list element.parameterList.parameters as parameter> + * @param ${parameter.name} the ${paramNames[parameter.name]}\n +</#list> +<#if element.throwsList.referenceElements?has_content> + *\n +</#if> +<#list element.throwsList.referenceElements as exception> + * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n +</#list> + */ + + + + + ^.*(public|protected|private)*\s*.*(\w(\s*<.+>)*)+\s+get\w+\s*\(.*\).+ + /**\n + * Gets ${partName}.\n +<#if element.typeParameters?has_content> * \n +</#if> +<#list element.typeParameters as typeParameter> + * @param <${typeParameter.name}> the type parameter\n +</#list> +<#if element.parameterList.parameters?has_content> + *\n +</#if> +<#list element.parameterList.parameters as parameter> + * @param ${parameter.name} the ${paramNames[parameter.name]}\n +</#list> +<#if isNotVoid> + *\n + * @return the ${partName}\n +</#if> +<#if element.throwsList.referenceElements?has_content> + *\n +</#if> +<#list element.throwsList.referenceElements as exception> + * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n +</#list> + */ + + + ^.*(public|protected|private)*\s*.*(void|\w(\s*<.+>)*)+\s+set\w+\s*\(.*\).+ + /**\n + * Sets ${partName}.\n +<#if element.typeParameters?has_content> * \n +</#if> +<#list element.typeParameters as typeParameter> + * @param <${typeParameter.name}> the type parameter\n +</#list> +<#if element.parameterList.parameters?has_content> + *\n +</#if> +<#list element.parameterList.parameters as parameter> + * @param ${parameter.name} the ${paramNames[parameter.name]}\n +</#list> +<#if isNotVoid> + *\n + * @return the ${partName}\n +</#if> +<#if element.throwsList.referenceElements?has_content> + *\n +</#if> +<#list element.throwsList.referenceElements as exception> + * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n +</#list> + */ + + + ^.*((public\s+static)|(static\s+public))\s+void\s+main\s*\(\s*String\s*(\[\s*\]|\.\.\.)\s+\w+\s*\).+ + /**\n + * The entry point of application.\n + + <#if element.parameterList.parameters?has_content> + *\n +</#if> + * @param ${element.parameterList.parameters[0].name} the input arguments\n +<#if element.throwsList.referenceElements?has_content> + *\n +</#if> +<#list element.throwsList.referenceElements as exception> + * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n +</#list> + */ + + + .+ + /**\n + * ${name}<#if isNotVoid> ${return}</#if>.\n +<#if element.typeParameters?has_content> * \n +</#if> +<#list element.typeParameters as typeParameter> + * @param <${typeParameter.name}> the type parameter\n +</#list> +<#if element.parameterList.parameters?has_content> + *\n +</#if> +<#list element.parameterList.parameters as parameter> + * @param ${parameter.name} the ${paramNames[parameter.name]}\n +</#list> +<#if isNotVoid> + *\n + * @return the ${return}\n +</#if> +<#if element.throwsList.referenceElements?has_content> + *\n +</#if> +<#list element.throwsList.referenceElements as exception> + * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n +</#list> + */ + + + + + ^.*(public|protected|private)*.+static.*(\w\s\w)+.+ + /**\n + * The constant ${element.getName()}.\n + */ + + + ^.*(public|protected|private)*.*(\w\s\w)+.+ + /**\n + <#if element.parent.isInterface()> + * The constant ${element.getName()}.\n +<#else> + * The ${name}.\n +</#if> */ + + + .+ + /**\n + <#if element.parent.isEnum()> + *${name} ${typeName}.\n +<#else> + * The ${name}.\n +</#if>*/ + + + + + \ No newline at end of file diff --git a/.idea/libraries/bld.xml b/.idea/libraries/bld.xml index cf75013..153a060 100644 --- a/.idea/libraries/bld.xml +++ b/.idea/libraries/bld.xml @@ -2,11 +2,12 @@ - + - + + @@ -14,4 +15,4 @@ - \ No newline at end of file + diff --git a/.idea/libraries/compile.xml b/.idea/libraries/compile.xml index 9bd86aa..99cc0c0 100644 --- a/.idea/libraries/compile.xml +++ b/.idea/libraries/compile.xml @@ -7,7 +7,7 @@ - - + + \ No newline at end of file diff --git a/.idea/libraries/runtime.xml b/.idea/libraries/runtime.xml index 2ae5c4b..d4069f2 100644 --- a/.idea/libraries/runtime.xml +++ b/.idea/libraries/runtime.xml @@ -8,7 +8,7 @@ - - + + \ No newline at end of file diff --git a/.idea/libraries/test.xml b/.idea/libraries/test.xml index b80486a..57ed5ef 100644 --- a/.idea/libraries/test.xml +++ b/.idea/libraries/test.xml @@ -8,7 +8,7 @@ - - + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index f03c702..1bf9192 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,3 +1,4 @@ + @@ -8,6 +9,18 @@ \ No newline at end of file + diff --git a/examples/.idea/libraries/compile.xml b/examples/.idea/libraries/compile.xml index 9bd86aa..99cc0c0 100644 --- a/examples/.idea/libraries/compile.xml +++ b/examples/.idea/libraries/compile.xml @@ -7,7 +7,7 @@ - - + + \ No newline at end of file diff --git a/examples/.idea/libraries/runtime.xml b/examples/.idea/libraries/runtime.xml index 2ae5c4b..d4069f2 100644 --- a/examples/.idea/libraries/runtime.xml +++ b/examples/.idea/libraries/runtime.xml @@ -8,7 +8,7 @@ - - + + \ No newline at end of file diff --git a/examples/.idea/libraries/test.xml b/examples/.idea/libraries/test.xml index b80486a..57ed5ef 100644 --- a/examples/.idea/libraries/test.xml +++ b/examples/.idea/libraries/test.xml @@ -8,7 +8,7 @@ - - + + \ No newline at end of file diff --git a/examples/.idea/misc.xml b/examples/.idea/misc.xml index 7e477ca..a01a1f3 100644 --- a/examples/.idea/misc.xml +++ b/examples/.idea/misc.xml @@ -1,5 +1,8 @@ - + + + + + \ No newline at end of file diff --git a/examples/.vscode/settings.json b/examples/.vscode/settings.json index 133aa45..ba429d0 100644 --- a/examples/.vscode/settings.json +++ b/examples/.vscode/settings.json @@ -3,13 +3,13 @@ "src/main/java", "src/main/resources", "src/test/java", - "src/bld/java" + "src/test/resources", + "src/bld/java", + "src/bld/resources" ], "java.configuration.updateBuildConfiguration": "automatic", "java.project.referencedLibraries": [ - "${HOME}/.bld/dist/bld-1.7.5.jar", - "lib/compile/*.jar", - "lib/runtime/*.jar", - "lib/test/*.jar" + "${HOME}/.bld/dist/bld-2.2.1.jar", + "lib/**/*.jar" ] } diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..8fcbd04 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,6 @@ +# Compile and Run Checkstyle + +```console +./bld compile checkstyle +``` + diff --git a/examples/lib/bld/bld-wrapper.jar b/examples/lib/bld/bld-wrapper.jar index e9d9403..862a228 100644 Binary files a/examples/lib/bld/bld-wrapper.jar and b/examples/lib/bld/bld-wrapper.jar differ diff --git a/examples/lib/bld/bld-wrapper.properties b/examples/lib/bld/bld-wrapper.properties index 8ac95b9..ab1936c 100644 --- a/examples/lib/bld/bld-wrapper.properties +++ b/examples/lib/bld/bld-wrapper.properties @@ -1,7 +1,7 @@ bld.downloadExtensionJavadoc=false bld.downloadExtensionSources=true -bld.extensions=com.uwyn.rife2:bld-checkstyle:0.9.0-SNAPSHOT -bld.repositories=MAVEN_LOCAL,MAVEN_CENTRAL,RIFE2_RELEASES bld.downloadLocation= +bld.extension-checkstyle=com.uwyn.rife2:bld-checkstyle:1.0.14 +bld.repositories=MAVEN_LOCAL,MAVEN_CENTRAL,RIFE2_SNAPSHOTS,RIFE2_RELEASES bld.sourceDirectories= -bld.version=1.7.5 +bld.version=2.2.1 diff --git a/examples/src/bld/java/com/example/ExamplesBuild.java b/examples/src/bld/java/com/example/ExamplesBuild.java index daf4979..af647ee 100644 --- a/examples/src/bld/java/com/example/ExamplesBuild.java +++ b/examples/src/bld/java/com/example/ExamplesBuild.java @@ -5,6 +5,9 @@ import rife.bld.BuildCommand; import rife.bld.extension.CheckstyleOperation; import java.util.List; +import java.util.logging.ConsoleHandler; +import java.util.logging.Level; +import java.util.logging.Logger; import static rife.bld.dependencies.Repository.MAVEN_CENTRAL; import static rife.bld.dependencies.Scope.*; @@ -16,19 +19,33 @@ public class ExamplesBuild extends BaseProject { mainClass = "com.example.ExamplesMain"; version = version(0, 1, 0); + javaRelease = 17; + + autoDownloadPurge = true; downloadSources = true; + repositories = List.of(MAVEN_CENTRAL); - scope(test).include(dependency("com.puppycrawl.tools", "checkstyle", version(10, 12, 4))); + scope(test).include(dependency("com.puppycrawl.tools", "checkstyle", version(10, 23, 0))); testOperation().mainClass("com.example.ExamplesTest"); } public static void main(String[] args) { + // Enable detailed logging for the extensions + var level = Level.ALL; + var logger = Logger.getLogger("rife.bld.extension"); + var consoleHandler = new ConsoleHandler(); + + consoleHandler.setLevel(level); + logger.addHandler(consoleHandler); + logger.setLevel(level); + logger.setUseParentHandlers(false); + new ExamplesBuild().start(args); } - @BuildCommand(summary = "Check code style") + @BuildCommand(summary = "Check code style using Sun coding conventions") public void checkstyle() throws Exception { new CheckstyleOperation() .fromProject(this) @@ -36,4 +53,11 @@ public class ExamplesBuild extends BaseProject { .execute(); } -} \ No newline at end of file + @BuildCommand(value = "checkstyle-custom", summary = "Check code style using custom coding conventions") + public void checkstyleCustom() throws Exception { + new CheckstyleOperation() + .fromProject(this) + .configurationFile("src/test/resources/checkstyle.xml") + .execute(); + } +} diff --git a/examples/src/test/resources/checkstyle.xml b/examples/src/test/resources/checkstyle.xml new file mode 100644 index 0000000..e601ecb --- /dev/null +++ b/examples/src/test/resources/checkstyle.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/lib/bld/bld-wrapper.jar b/lib/bld/bld-wrapper.jar index e9d9403..ee9e249 100644 Binary files a/lib/bld/bld-wrapper.jar and b/lib/bld/bld-wrapper.jar differ diff --git a/lib/bld/bld-wrapper.properties b/lib/bld/bld-wrapper.properties index f8b51d9..2b5c0ac 100644 --- a/lib/bld/bld-wrapper.properties +++ b/lib/bld/bld-wrapper.properties @@ -1,8 +1,8 @@ bld.downloadExtensionJavadoc=false bld.downloadExtensionSources=true -bld.extension-pmd=com.uwyn.rife2:bld-pmd:0.9.2 -bld.extension-jacoco=com.uwyn.rife2:bld-jacoco-report:0.9.0 -bld.repositories=MAVEN_CENTRAL,RIFE2_SNAPSHOTS,RIFE2_RELEASES bld.downloadLocation= +bld.extension-exec=com.uwyn.rife2:bld-exec:1.0.5 +bld.extension-pmd=com.uwyn.rife2:bld-pmd:1.2.2 +bld.repositories=MAVEN_CENTRAL,MAVEN_LOCAL,RIFE2_SNAPSHOTS,RIFE2_RELEASES bld.sourceDirectories= -bld.version=1.7.5 +bld.version=2.2.1 diff --git a/scripts/checkcliargs.sh b/scripts/checkcliargs.sh new file mode 100755 index 0000000..1ed3db1 --- /dev/null +++ b/scripts/checkcliargs.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +main="com.puppycrawl.tools.checkstyle.Main" +new=/tmp/checkcliargs-new +old=/tmp/checkcliargs-old + +java -cp "lib/test/*" $main --help >$new +java -cp "examples/lib/test/*" $main --help >$old + +if [ "$1" == "-v" ]; then + code --wait --diff $old $new +else + diff $old $new +fi + +rm -rf $new $old diff --git a/scripts/cliargs.sh b/scripts/cliargs.sh new file mode 100755 index 0000000..3c9bc28 --- /dev/null +++ b/scripts/cliargs.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +java -cp "lib/test/*" com.puppycrawl.tools.checkstyle.Main --help |\ +grep "^ -.*" |\ +sed -e "s/ -/-/" -e "s/[,=].*//" -e '/-V/d' -e '/-h/d' |\ +sort > "src/test/resources/checkstyle-args.txt" diff --git a/src/bld/java/rife/bld/extension/CheckstyleOperationBuild.java b/src/bld/java/rife/bld/extension/CheckstyleOperationBuild.java index 69d586b..dc827f2 100644 --- a/src/bld/java/rife/bld/extension/CheckstyleOperationBuild.java +++ b/src/bld/java/rife/bld/extension/CheckstyleOperationBuild.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,53 +22,65 @@ import rife.bld.publish.PublishDeveloper; import rife.bld.publish.PublishLicense; import rife.bld.publish.PublishScm; -import java.io.IOException; import java.util.List; +import java.util.Locale; -import static rife.bld.dependencies.Repository.MAVEN_CENTRAL; -import static rife.bld.dependencies.Repository.RIFE2_RELEASES; -import static rife.bld.dependencies.Scope.*; +import static rife.bld.dependencies.Repository.*; +import static rife.bld.dependencies.Scope.compile; +import static rife.bld.dependencies.Scope.test; import static rife.bld.operations.JavadocOptions.DocLinkOption.NO_MISSING; public class CheckstyleOperationBuild extends Project { public CheckstyleOperationBuild() { pkg = "rife.bld.extension"; name = "CheckstyleOperation"; - version = version(0, 9, 0, "SNAPSHOT"); + version = version(1, 0, 15, "SNAPSHOT"); javaRelease = 17; + downloadSources = true; autoDownloadPurge = true; - repositories = List.of(MAVEN_CENTRAL, RIFE2_RELEASES); + + repositories = List.of(MAVEN_LOCAL, MAVEN_CENTRAL, RIFE2_RELEASES, RIFE2_SNAPSHOTS); scope(compile) - .include(dependency("com.uwyn.rife2", "bld", version(1, 7, 5))); + .include(dependency("com.uwyn.rife2", "bld", version(2, 2, 1))); scope(test) - .include(dependency("com.puppycrawl.tools", "checkstyle", version(10, 12, 4))) - .include(dependency("org.jsoup", "jsoup", version(1, 16, 2))) - .include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 10, 0))) - .include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 10, 0))) - .include(dependency("org.assertj", "assertj-core", version(3, 24, 2))); + .include(dependency("com.puppycrawl.tools", "checkstyle", version(10, 23, 0))) + .include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 12, 1))) + .include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 12, 1))) + .include(dependency("org.assertj", "assertj-core", version(3, 27, 3))); + javadocOperation() .javadocOptions() + .author() .docLint(NO_MISSING) .link("https://rife2.github.io/bld/") .link("https://rife2.github.io/rife2/"); publishOperation() .repository(version.isSnapshot() ? repository("rife2-snapshot") : repository("rife2")) + .repository(repository("github")) .info() .groupId("com.uwyn.rife2") .artifactId("bld-checkstyle") - .description("bld Checkstyle Extensions") + .description("bld Checkstyle Extension") .url("https://github.com/rife2/bld-checkstyle") - .developer(new PublishDeveloper().id("ethauvin").name("Erik C. Thauvin").email("erik@thauvin.net") - .url("https://erik.thauvin.net/")) - .license(new PublishLicense().name("The Apache License, Version 2.0") - .url("http://www.apache.org/licenses/LICENSE-2.0.txt")) - .scm(new PublishScm().connection("scm:git:https://github.com/rife2/bld-checkstyle.git") + .developer(new PublishDeveloper() + .id("ethauvin") + .name("Erik C. Thauvin") + .email("erik@thauvin.net") + .url("https://erik.thauvin.net/") + ) + .license(new PublishLicense() + .name("The Apache License, Version 2.0") + .url("https://www.apache.org/licenses/LICENSE-2.0.txt") + ) + .scm(new PublishScm() + .connection("scm:git:https://github.com/rife2/bld-checkstyle.git") .developerConnection("scm:git:git@github.com:rife2/bld-checkstyle.git") - .url("https://github.com/rife2/bld-checkstyle")) + .url("https://github.com/rife2/bld-checkstyle") + ) .signKey(property("sign.key")) .signPassphrase(property("sign.passphrase")); } @@ -77,19 +89,24 @@ public class CheckstyleOperationBuild extends Project { new CheckstyleOperationBuild().start(args); } - @BuildCommand(summary = "Generates JaCoCo Reports") - public void jacoco() throws IOException { - new JacocoReportOperation() - .fromProject(this) - .execute(); - } - @BuildCommand(summary = "Runs PMD analysis") - public void pmd() { + public void pmd() throws Exception { new PmdOperation() .fromProject(this) .failOnViolation(true) .ruleSets("config/pmd.xml") .execute(); } + + @Override + public void test() throws Exception { + var os = System.getProperty("os.name"); + if (os != null && os.toLowerCase(Locale.US).contains("linux")) { + new ExecOperation() + .fromProject(this) + .command("scripts/cliargs.sh") + .execute(); + } + super.test(); + } } diff --git a/src/main/java/rife/bld/extension/CheckstyleOperation.java b/src/main/java/rife/bld/extension/CheckstyleOperation.java index 8237736..97eeb55 100644 --- a/src/main/java/rife/bld/extension/CheckstyleOperation.java +++ b/src/main/java/rife/bld/extension/CheckstyleOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,11 +17,16 @@ package rife.bld.extension; import rife.bld.BaseProject; +import rife.bld.extension.checkstyle.OutputFormat; import rife.bld.operations.AbstractProcessOperation; +import rife.bld.operations.exceptions.ExitStatusException; +import java.io.File; +import java.io.IOException; import java.nio.file.Path; import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; import java.util.logging.Logger; /** @@ -32,22 +37,23 @@ import java.util.logging.Logger; */ public class CheckstyleOperation extends AbstractProcessOperation { private static final Logger LOGGER = Logger.getLogger(CheckstyleOperation.class.getName()); - /** - * The command line options. - */ - protected final Map options = new ConcurrentHashMap<>(); + private final Collection excludeRegex_ = new ArrayList<>(); + private final Collection exclude_ = new ArrayList<>(); + private final Map options_ = new ConcurrentHashMap<>(); + private final Set sourceDir_ = new TreeSet<>(); - /** - * The source files(s) or folder(s). - */ - protected final Set sourceDirs = new TreeSet<>(); private BaseProject project_; /** * Shows Abstract Syntax Tree(AST) branches that match given XPath query. + * + * @param xPathQuery the xPath query + * @return the checkstyle operation */ public CheckstyleOperation branchMatchingXpath(String xPathQuery) { - options.put("-b", xPathQuery); + if (isNotBlank(xPathQuery)) { + options_.put("-b", xPathQuery); + } return this; } @@ -55,88 +61,216 @@ public class CheckstyleOperation extends AbstractProcessOperation paths) { - for (var p : paths) { - options.put("-e", p); - } + public CheckstyleOperation exclude(File... path) { + return exclude(List.of(path)); + } + + /** + * Directory/file to exclude from Checkstyle. The path can be the full, absolute path, or relative to the current + * path. Multiple excludes are allowed. + * + * @param path one or more paths + * @return the checkstyle operation + * @see #excludePaths(Collection) + */ + public CheckstyleOperation exclude(Path... path) { + return excludePaths(List.of(path)); + } + + /** + * Directory/file to exclude from Checkstyle. The path can be the full, absolute path, or relative to the current + * path. Multiple excludes are allowed. + * + * @param paths the paths + * @return the checkstyle operation + * @see #exclude(File...) + */ + public CheckstyleOperation exclude(Collection paths) { + exclude_.addAll(paths); return this; } /** - * Directory/file pattern to exclude from CheckStyle. Multiple excludes are allowed. + * Directory/file to exclude from Checkstyle. The path can be the full, absolute path, or relative to the current + * path. Multiple excludes are allowed. + * + * @param paths the paths + * @return the checkstyle operation + * @see #exclude(Path...) */ - public CheckstyleOperation excludedPathPattern(String pattern) { - options.put("-x", pattern); + public CheckstyleOperation excludePaths(Collection paths) { + return exclude(paths.stream().map(Path::toFile).toList()); + } + + /** + * Directory/file pattern to exclude from Checkstyle. Multiple exclude are allowed. + * + * @param regex the pattern to exclude + * @return the checkstyle operation + * @see #excludeRegex(Collection) + */ + public CheckstyleOperation excludeRegex(String... regex) { + return excludeRegex(List.of(regex)); + } + + /** + * Directory/file pattern to exclude from Checkstyle. Multiple exclude are allowed. + * + * @param regex the patterns to exclude + * @return the checkstyle operation + * @see #excludeRegex(String...) + */ + public CheckstyleOperation excludeRegex(Collection regex) { + excludeRegex_.addAll(regex); return this; } + /** + * Directory/file to exclude from Checkstyle. The path can be the full, absolute path, or relative to the current + * path. Multiple excludes are allowed. + * + * @param paths the paths + * @return the checkstyle operation + * @see #exclude(String...) + */ + public CheckstyleOperation excludeStrings(Collection paths) { + return exclude(paths.stream().map(File::new).toList()); + } + + @Override + public void execute() throws IOException, InterruptedException, ExitStatusException { + if (project_ == null) { + if (LOGGER.isLoggable(Level.SEVERE) && !silent()) { + LOGGER.severe("A project must be specified."); + } + throw new ExitStatusException(ExitStatusException.EXIT_FAILURE); + } else { + super.execute(); + } + } + /** * Part of the {@link #execute} operation, constructs the command list * to use for building the process. */ @Override protected List executeConstructProcessCommandList() { - if (project_ == null) { - LOGGER.severe("A project must be specified."); - } else if (sourceDirs.isEmpty()) { - sourceDirs.add(project_.srcMainJavaDirectory().getPath()); - sourceDirs.add(project_.srcTestJavaDirectory().getPath()); - } - final List args = new ArrayList<>(); - args.add(javaTool()); - args.add("-cp"); - args.add(String.format("%s:%s:%s:%s", Path.of(project_.libTestDirectory().getPath(), "*"), - Path.of(project_.libCompileDirectory().getPath(), "*"), project_.buildMainDirectory(), - project_.buildTestDirectory())); - args.add("com.puppycrawl.tools.checkstyle.Main"); - - options.forEach((k, v) -> { - args.add(k); - if (!v.isEmpty()) { - args.add(v); + if (project_ != null) { + if (sourceDir_.isEmpty()) { + sourceDir_.add(project_.srcMainJavaDirectory()); + sourceDir_.add(project_.srcTestJavaDirectory()); } - }); + args.add(javaTool()); - args.addAll(sourceDirs); + args.add("-cp"); + args.add(String.format("%s%s%s%s%s%s%s", new File(project_.libTestDirectory(), "*"), + File.pathSeparator, new File(project_.libCompileDirectory(), "*"), File.pathSeparator, + project_.buildMainDirectory(), File.pathSeparator, project_.buildTestDirectory())); + args.add("com.puppycrawl.tools.checkstyle.Main"); + + options_.forEach((k, v) -> { + args.add(k); + if (!v.isEmpty()) { + args.add(v); + } + }); + + if (!exclude_.isEmpty()) { + for (var e : exclude_) { + if (e.exists()) { + args.add("-e"); + args.add(e.getAbsolutePath()); + } + } + } + + if (!excludeRegex_.isEmpty()) { + for (var e : excludeRegex_) { + if (isNotBlank(e)) { + args.add("-x"); + args.add(e); + } + } + } + + args.addAll(sourceDir_.stream().map(File::getAbsolutePath).toList()); + + if (LOGGER.isLoggable(Level.FINE)) { + LOGGER.log(Level.FINE, String.join(" ", args)); + } + } return args; } @@ -152,22 +286,31 @@ public class CheckstyleOperation extends AbstractProcessOperation + * Defaults to {@link OutputFormat#PLAIN}. + * + * @param format the output format + * @return the checkstyle operation */ - public CheckstyleOperation format(String format) { - options.put("-f", format); + public CheckstyleOperation format(OutputFormat format) { + options_.put("-f", format.label.toLowerCase()); return this; } @@ -175,128 +318,279 @@ public class CheckstyleOperation extends AbstractProcessOperationonly Javadoc comment content - * without including '/**' and '*/' at the beginning and at the end respectively. The option cannot - * be used other options and requires exactly one file to run on to be specified. + * Returns the command line options. + * + * @return the command line options */ - public CheckstyleOperation javadocTree(boolean isTree) { - if (isTree) { - options.put("-j", ""); - } else { - options.remove("-j"); + public Map options() { + return options_; + } + + /** + * Sets the output file. + *

+ * Defaults to stdout. + * + * @param file the output file + * @return the checkstyle operation + */ + public CheckstyleOperation outputPath(String file) { + if (isNotBlank(file)) { + options_.put("-o", file); } return this; } + /** + * Sets the output file. + *

+ * Defaults to stdout. + * + * @param file the output file + * @return the checkstyle operation + */ + public CheckstyleOperation outputPath(File file) { + return outputPath(file.getAbsolutePath()); + } + + /** + * Sets the output file. + *

+ * Defaults to stdout. + * + * @param file the output file + * @return the checkstyle operation + */ + public CheckstyleOperation outputPath(Path file) { + return outputPath(file.toFile().getAbsolutePath()); + } + + /** + * Sets the property files to load. + * + * @param file the file + * @return the checkstyle operation + */ + public CheckstyleOperation propertiesFile(String file) { + if (isNotBlank(file)) { + options_.put("-p", file); + } + return this; + } + + /** + * Sets the property files to load. + * + * @param file the file + * @return the checkstyle operation + */ + public CheckstyleOperation propertiesFile(File file) { + return propertiesFile(file.getAbsolutePath()); + } + + /** + * Sets the property files to load. + * + * @param file the file + * @return the checkstyle operation + */ + public CheckstyleOperation propertiesFile(Path file) { + return propertiesFile(file.toFile().getAbsolutePath()); + } + + /** + * Specifies the file(s) or folder(s) containing the source files to check. + * + * @param dir one or more directories + * @return the checkstyle operation + * @see #sourceDirStrings(Collection) + */ + public CheckstyleOperation sourceDir(String... dir) { + return sourceDirStrings(List.of(dir)); + } + + /** + * Specifies the file(s) or folder(s) containing the source files to check. + * + * @param dir one or more directories + * @return the checkstyle operation + * @see #sourceDir(Collection) + */ + public CheckstyleOperation sourceDir(File... dir) { + return sourceDir(List.of(dir)); + } + + /** + * Specifies the file(s) or folder(s) containing the source files to check. + * + * @param dir one or more directories + * @return the checkstyle operation + * @see #sourceDirPaths(Collection) + */ + public CheckstyleOperation sourceDir(Path... dir) { + return sourceDirPaths(List.of(dir)); + } + + /** + * Specifies the file(s) or folder(s) containing the source files to check. + * + * @param dirs the directories + * @return the checkstyle operation + * @see #sourceDir(File...) + */ + public CheckstyleOperation sourceDir(Collection dirs) { + sourceDir_.addAll(dirs); + return this; + } + + /** + * Returns the file(s) or folders(s) containing the sources files to check + * + * @return the files or directories + */ + public Set sourceDir() { + return sourceDir_; + } + + /** + * Specifies the file(s) or folder(s) containing the source files to check. + * + * @param dirs the directories + * @return the checkstyle operation + * @see #sourceDir(Path...) + */ + public CheckstyleOperation sourceDirPaths(Collection dirs) { + return sourceDir(dirs.stream().map(Path::toFile).toList()); + } + + /** + * Specifies the file(s) or folder(s) containing the source files to check. + * + * @param dirs the directories + * @return the checkstyle operation + * @see #sourceDir(String...) + */ + public CheckstyleOperation sourceDirStrings(Collection dirs) { + return sourceDir(dirs.stream().map(File::new).toList()); + } + /** * Prints xpath suppressions at the file's line and column position. Argument is the line and column number * (separated by a {@code :} ) in the file that the suppression should be generated for. The option cannot be * used with other options and requires exactly one file to run on to be specified. *

- * ATTENTION: generated result will have few queries, joined by pipe(|). Together they will match all AST nodes - * on specified line and column. You need to choose only one and recheck that it works. Usage of all of them is also - * ok, but might result in undesirable matching and suppress other issues. - */ - public CheckstyleOperation lineColumn(String lineColumn) { - options.put("-s", lineColumn); - return this; - } - - /** - * Sets the output file. Defaults to stdout. - */ - public CheckstyleOperation output(String file) { - options.put("-o", file); - return this; - } - - /** - * Sets the property files to load. - */ - public CheckstyleOperation propertiesFile(String file) { - options.put("-p", file); - return this; - } - - /** - * Specified the file(s) or folder(s) containing the source files to check. + * Note that the generated result will have few queries, joined by pipe({@code |}). Together they will match all + * AST nodes on specified line and column. You need to choose only one and recheck that it works. Usage of all of + * them is also ok, but might result in undesirable matching and suppress other issues. * - * @see #sourceDir(Collection) + * @param lineColumnNumber the line column number + * @return the checkstyle operation */ - public CheckstyleOperation sourceDir(String... dir) { - sourceDirs.addAll(Arrays.asList(dir)); + public CheckstyleOperation suppressionLineColumnNumber(String lineColumnNumber) { + if (isNotBlank(lineColumnNumber)) { + options_.put("-s", lineColumnNumber); + } return this; } /** - * Specified the file(s) or folder(s) containing the source files to check. - * - * @see #sourceDir(String...) - */ - public CheckstyleOperation sourceDir(Collection dirs) { - sourceDirs.addAll(dirs); - return this; - } - - /** - * Sets the length of the tab character. Used only with the {@link #lineColumn(String) lineColum} option. + * Sets the length of the tab character. Used only with the + * {@link #suppressionLineColumnNumber(String) suppressionLineColumnNumber} option. + *

* Default value is {@code 8}. + * + * @param length the length + * @return the checkstyle operation */ public CheckstyleOperation tabWith(int length) { - options.put("-w", String.valueOf(length)); + options_.put("-w", String.valueOf(length)); return this; } /** - * Prints Abstract Syntax Tree(AST) of the checked file. The option cannot be used other options and requires - * exactly one file to run on to be specified. + * This option is used to display the Abstract Syntax Tree (AST) without any comments of the specified file. It can + * only be used on a single file and cannot be combined with other options. + * + * @param isTree {@code true} or {@code false} + * @return the checkstyle operation */ public CheckstyleOperation tree(boolean isTree) { if (isTree) { - options.put("-t", ""); + options_.put("-t", ""); } else { - options.remove("-t"); + options_.remove("-t"); } return this; } /** - * Prints Abstract Syntax Tree(AST) with comment nodes of the checked file. The option cannot be used with other - * options and requires exactly one file to run on to be specified. + * This option is used to display the Abstract Syntax Tree (AST) with comment nodes excluding Javadoc of the + * specified file. It can only be used on a single file and cannot be combined with other options. + * + * @param isTree {@code true} or {@code false} + * @return the checkstyle operation */ public CheckstyleOperation treeWithComments(boolean isTree) { if (isTree) { - options.put("-T", ""); + options_.put("-T", ""); } else { - options.remove("-T"); + options_.remove("-T"); } return this; } /** - * Prints Abstract Syntax Tree(AST) with Javadoc nodes and comment nodes of the checked file. Attention that line - * number and columns will not be the same as it is a file due to the fact that each javadoc comment is parsed - * separately from java file. The option cannot be used with other options and requires exactly one file to run on - * to be specified. + * This option is used to display the Abstract Syntax Tree (AST) with Javadoc nodes of the specified file. It can + * only be used on a single file and cannot be combined with other options. + * + * @param isTree {@code true} or {@code false} + * @return the checkstyle operation */ public CheckstyleOperation treeWithJavadoc(boolean isTree) { if (isTree) { - options.put("-J", ""); + options_.put("-J", ""); } else { - options.remove("-J"); + options_.remove("-J"); } return this; } -} \ No newline at end of file +} diff --git a/src/main/java/rife/bld/extension/checkstyle/OutputFormat.java b/src/main/java/rife/bld/extension/checkstyle/OutputFormat.java new file mode 100644 index 0000000..0ba8021 --- /dev/null +++ b/src/main/java/rife/bld/extension/checkstyle/OutputFormat.java @@ -0,0 +1,35 @@ +/* + * Copyright 2023-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package rife.bld.extension.checkstyle; + +/** + * The Checkstyle output format for XML, sarif and default (plain) logger. + */ +public enum OutputFormat { + XML("xml"), + SARIF("sarif"), + PLAIN("plain"); + + public final String label; + + /** + * Sets the label of this output format. + */ + OutputFormat(String label) { + this.label = label; + } +} \ No newline at end of file diff --git a/src/test/java/rife/bld/extension/CheckstyleOperationTest.java b/src/test/java/rife/bld/extension/CheckstyleOperationTest.java index 945e286..0d0e1b2 100644 --- a/src/test/java/rife/bld/extension/CheckstyleOperationTest.java +++ b/src/test/java/rife/bld/extension/CheckstyleOperationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,58 +16,150 @@ package rife.bld.extension; +import org.assertj.core.api.AutoCloseableSoftAssertions; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledOnOs; +import org.junit.jupiter.api.condition.OS; import rife.bld.BaseProject; import rife.bld.Project; import rife.bld.WebProject; +import rife.bld.extension.checkstyle.OutputFormat; import rife.bld.operations.exceptions.ExitStatusException; import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.List; +import java.util.logging.ConsoleHandler; +import java.util.logging.Level; +import java.util.logging.Logger; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; - class CheckstyleOperationTest { + public static final String SRC_MAIN_JAVA = "src/main/java"; + public static final String SRC_TEST_JAVA = "src/test/java"; private static final String ADD = "add"; private static final String BAR = "bar"; private static final String FOO = "foo"; private static final String REMOVE = "remove"; + @BeforeAll + static void beforeAll() { + var level = Level.ALL; + var logger = Logger.getLogger("rife.bld.extension"); + var consoleHandler = new ConsoleHandler(); + consoleHandler.setLevel(level); + logger.addHandler(consoleHandler); + logger.setLevel(level); + logger.setUseParentHandlers(false); + } + + @Test void branchMatchingXpath() { var op = new CheckstyleOperation().fromProject(new Project()).branchMatchingXpath(FOO); - assertThat(op.options.get("-b")).isEqualTo(FOO); + assertThat(op.options().get("-b")).isEqualTo(FOO); + } + + @Test + @EnabledOnOs(OS.LINUX) + void checkAllParameters() throws IOException { + var args = Files.readAllLines(Paths.get("src", "test", "resources", "checkstyle-args.txt")); + + assertThat(args).isNotEmpty(); + + var params = new CheckstyleOperation() + .fromProject(new Project()) + .branchMatchingXpath("xpath") + .debug(true) + .configurationFile(new File("config")) + .exclude(SRC_MAIN_JAVA) + .excludeRegex("regex") + .executeIgnoredModules(true) + .format(OutputFormat.XML) + .generateXpathSuppression(true) + .javadocTree(true) + .outputPath(new File("optionPath")) + .propertiesFile(new File("properties")) + .suppressionLineColumnNumber("12") + .tabWith(1) + .tree(true) + .treeWithComments(true) + .treeWithJavadoc(true) + .executeConstructProcessCommandList(); + + try (var softly = new AutoCloseableSoftAssertions()) { + for (var p : args) { + var found = false; + for (var a : params) { + if (a.startsWith(p)) { + found = true; + break; + } + } + softly.assertThat(found).as(p + " not found.").isTrue(); + } + } } @Test void configurationFile() { var op = new CheckstyleOperation().fromProject(new Project()).configurationFile(FOO); - assertThat(op.options.get("-c")).isEqualTo(FOO); + assertThat(op.options().get("-c")).isEqualTo(FOO); } @Test void debug() { var op = new CheckstyleOperation().fromProject(new Project()).debug(true); - assertThat(op.options.containsKey("-d")).as(ADD).isTrue(); + assertThat(op.options().containsKey("-d")).as(ADD).isTrue(); op = op.debug(false); - assertThat(op.options.containsKey("-d")).as(REMOVE).isFalse(); + assertThat(op.options().containsKey("-d")).as(REMOVE).isFalse(); } @Test void exclude() { - var op = new CheckstyleOperation().fromProject(new Project()).exclude(FOO); - assertThat(op.options.get("-e")).isEqualTo(FOO); - op = new CheckstyleOperation().fromProject(new Project()).exclude(List.of(FOO)); - assertThat(op.options.get("-e")).as("as list").isEqualTo(FOO); + var foo = new File(SRC_MAIN_JAVA); + var bar = new File(SRC_TEST_JAVA); + var e = "-e "; + + var op = new CheckstyleOperation().fromProject(new Project()).exclude(SRC_MAIN_JAVA, SRC_TEST_JAVA); + assertThat(String.join(" ", op.executeConstructProcessCommandList())).as("String...") + .contains(e + foo.getAbsolutePath()).contains(e + bar.getAbsolutePath()); + + op = new CheckstyleOperation().fromProject(new Project()).excludeStrings(List.of(SRC_MAIN_JAVA, SRC_TEST_JAVA)); + assertThat(String.join(" ", op.executeConstructProcessCommandList())).as("List(String...)") + .contains(e + foo.getAbsolutePath()).contains(e + bar.getAbsolutePath()); + + op = new CheckstyleOperation().fromProject(new Project()).exclude(foo, bar); + assertThat(String.join(" ", op.executeConstructProcessCommandList())).as("File...") + .contains(e + foo.getAbsolutePath()).contains(e + bar.getAbsolutePath()); + + op = new CheckstyleOperation().fromProject(new Project()).exclude(List.of(foo, bar)); + assertThat(String.join(" ", op.executeConstructProcessCommandList())).as("List(File...)") + .contains(e + foo.getAbsolutePath()).contains(e + bar.getAbsolutePath()); + + op = new CheckstyleOperation().fromProject(new Project()).exclude(foo.toPath(), bar.toPath()); + assertThat(String.join(" ", op.executeConstructProcessCommandList())).as("Path...") + .contains(e + foo.getAbsolutePath()).contains(e + bar.getAbsolutePath()); + + op = new CheckstyleOperation().fromProject(new Project()).excludePaths(List.of(foo.toPath(), bar.toPath())); + assertThat(String.join(" ", op.executeConstructProcessCommandList())).as("List(Path...)") + .contains(e + foo.getAbsolutePath()).contains(e + bar.getAbsolutePath()); } @Test - void excludedPathPattern() { - var op = new CheckstyleOperation().fromProject(new Project()).excludedPathPattern(FOO); - assertThat(op.options.get("-x")).isEqualTo(FOO); + void excludeRegex() { + var op = new CheckstyleOperation().fromProject(new Project()).excludeRegex(FOO, BAR); + var x = "-x "; + assertThat(String.join(" ", op.executeConstructProcessCommandList())).contains(x + FOO, x + BAR); + + op = new CheckstyleOperation().fromProject(new Project()).excludeRegex(List.of(FOO, BAR)); + assertThat(String.join(" ", op.executeConstructProcessCommandList())).as("as list").contains(x + FOO, x + BAR); } @Test @@ -76,9 +168,9 @@ class CheckstyleOperationTest { tmpFile.deleteOnExit(); var op = new CheckstyleOperation() .fromProject(new WebProject()) - .sourceDir("src/main/java", "src/test/java") - .configurationFile("src/test/resources/google_checks.xml") - .output(tmpFile.getAbsolutePath()); + .sourceDir(SRC_MAIN_JAVA, SRC_TEST_JAVA) + .configurationFile(Path.of("src/test/resources/google_checks.xml")) + .outputPath(tmpFile.toPath()); op.execute(); assertThat(tmpFile).exists(); } @@ -91,7 +183,7 @@ class CheckstyleOperationTest { .propertiesFile("config/checkstyle.properties") .debug(true) .executeIgnoredModules(true) - .sourceDir("src/main/java", "src/test/java"); + .sourceDir(SRC_MAIN_JAVA, SRC_TEST_JAVA); assertThat(String.join(" ", op.executeConstructProcessCommandList())) .startsWith("java -cp ") .endsWith( @@ -100,15 +192,22 @@ class CheckstyleOperationTest { "-b xpath " + "-c config/checkstyle.xml " + "-d -E " + - "src/main/java src/test/java"); + new File(SRC_MAIN_JAVA).getAbsolutePath() + " " + + new File(SRC_TEST_JAVA).getAbsolutePath()); } @Test void executeIgnoredModules() { var op = new CheckstyleOperation().fromProject(new Project()).executeIgnoredModules(true); - assertThat(op.options.containsKey("-E")).as(ADD).isTrue(); + assertThat(op.options().containsKey("-E")).as(ADD).isTrue(); op = op.executeIgnoredModules(false); - assertThat(op.options.containsKey("-E")).as(REMOVE).isFalse(); + assertThat(op.options().containsKey("-E")).as(REMOVE).isFalse(); + } + + @Test + void executeNoProject() { + var op = new CheckstyleOperation(); + assertThatCode(op::execute).isInstanceOf(ExitStatusException.class); } @Test @@ -117,88 +216,115 @@ class CheckstyleOperationTest { tmpFile.deleteOnExit(); var op = new CheckstyleOperation() .fromProject(new WebProject()) - .sourceDir(List.of("src/main/java", "src/test/java")) + .sourceDir(SRC_MAIN_JAVA, SRC_TEST_JAVA) .configurationFile("src/test/resources/sun_checks.xml") - .output(tmpFile.getAbsolutePath()); + .outputPath(tmpFile.getAbsolutePath()); assertThatCode(op::execute).isInstanceOf(ExitStatusException.class); assertThat(tmpFile).exists(); } @Test void format() { - var op = new CheckstyleOperation().fromProject(new Project()).format(FOO); - assertThat(op.options.get("-f")).isEqualTo(FOO); + var op = new CheckstyleOperation().fromProject(new Project()).format(OutputFormat.XML); + assertThat(op.options().get("-f")).isEqualTo("xml"); } @Test void generateXpathSuppression() { var op = new CheckstyleOperation().fromProject(new Project()).generateXpathSuppression(true); - assertThat(op.options.containsKey("-g")).as(ADD).isTrue(); + assertThat(op.options().containsKey("-g")).as(ADD).isTrue(); op = op.generateXpathSuppression(false); - assertThat(op.options.containsKey("-g")).as(REMOVE).isFalse(); + assertThat(op.options().containsKey("-g")).as(REMOVE).isFalse(); } @Test void javadocTree() { var op = new CheckstyleOperation().fromProject(new Project()).javadocTree(true); - assertThat(op.options.containsKey("-j")).as(ADD).isTrue(); + assertThat(op.options().containsKey("-j")).as(ADD).isTrue(); op = op.javadocTree(false); - assertThat(op.options.containsKey("-j")).as(REMOVE).isFalse(); + assertThat(op.options().containsKey("-j")).as(REMOVE).isFalse(); } @Test - void lineColumn() { - var op = new CheckstyleOperation().fromProject(new Project()).lineColumn(FOO); - assertThat(op.options.get("-s")).isEqualTo(FOO); - } - - @Test - void output() { - var op = new CheckstyleOperation().fromProject(new Project()).output(FOO); - assertThat(op.options.get("-o")).isEqualTo(FOO); + void outputPath() { + var op = new CheckstyleOperation().fromProject(new Project()).outputPath(FOO); + assertThat(op.options().get("-o")).isEqualTo(FOO); } @Test void propertiesFile() { var op = new CheckstyleOperation().fromProject(new Project()).propertiesFile(FOO); - assertThat(op.options.get("-p")).isEqualTo(FOO); + assertThat(op.options().get("-p")).isEqualTo(FOO); + + var fooPath = Path.of(FOO); + op = op.propertiesFile(fooPath); + assertThat(op.options().get("-p")).isEqualTo(fooPath.toFile().getAbsolutePath()); } @Test void sourceDir() { - var op = new CheckstyleOperation().fromProject(new Project()).sourceDir(FOO); - assertThat(op.sourceDirs).contains(FOO); - op = op.sourceDir(FOO, BAR); - assertThat(op.sourceDirs).as("foo, bar").hasSize(2).contains(FOO).contains(BAR); + var foo = new File(FOO); + var bar = new File(BAR); + + var op = new CheckstyleOperation().fromProject(new Project()).sourceDir(FOO, BAR); + assertThat(op.sourceDir()).as("String...").hasSize(2).contains(foo, bar); + op.sourceDir().clear(); + + op = op.sourceDirStrings(List.of(FOO, BAR)); + assertThat(op.sourceDir()).as("List(String...)").hasSize(2).contains(foo, bar); + op.sourceDir().clear(); + + op = op.sourceDir(foo, bar); + assertThat(op.sourceDir()).as("File...").hasSize(2).contains(foo, bar); + op.sourceDir().clear(); + + op = op.sourceDir(List.of(foo, bar)); + assertThat(op.sourceDir()).as("List(File...)").hasSize(2).contains(foo, bar); + op.sourceDir().clear(); + + op = op.sourceDir(foo.toPath(), bar.toPath()); + assertThat(op.sourceDir()).as("Path...").hasSize(2).contains(foo, bar); + op.sourceDir().clear(); + + op = op.sourceDirPaths(List.of(foo.toPath(), bar.toPath())); + assertThat(op.sourceDir()).as("List(Path...)").hasSize(2).contains(foo, bar); + op.sourceDir().clear(); + } + + + @Test + void suppressionLineColumnNumber() { + var op = new CheckstyleOperation().fromProject(new Project()).suppressionLineColumnNumber(FOO + ':' + BAR); + assertThat(op.options().get("-s")).isEqualTo(FOO + ':' + BAR); } @Test void tabWith() { var op = new CheckstyleOperation().fromProject(new Project()).tabWith(9); - assertThat(op.options.get("-w")).isEqualTo("9"); + assertThat(op.options().get("-w")).isEqualTo("9"); } @Test void tree() { var op = new CheckstyleOperation().fromProject(new Project()).tree(true); - assertThat(op.options.containsKey("-t")).as(ADD).isTrue(); + assertThat(op.options().containsKey("-t")).as(ADD).isTrue(); op = op.tree(false); - assertThat(op.options.containsKey("-t")).as(REMOVE).isFalse(); + assertThat(op.options().containsKey("-t")).as(REMOVE).isFalse(); } @Test void treeWithComments() { var op = new CheckstyleOperation().fromProject(new Project()).treeWithComments(true); - assertThat(op.options.containsKey("-T")).as(ADD).isTrue(); + assertThat(op.options().containsKey("-T")).as(ADD).isTrue(); op = op.treeWithComments(false); - assertThat(op.options.containsKey("-T")).as(REMOVE).isFalse(); + assertThat(op.options().containsKey("-T")).as(REMOVE).isFalse(); } @Test void treeWithJavadoc() { var op = new CheckstyleOperation().fromProject(new Project()).treeWithJavadoc(true); - assertThat(op.options.containsKey("-J")).as(ADD).isTrue(); + assertThat(op.options().containsKey("-J")).as(ADD).isTrue(); op = op.treeWithJavadoc(false); - assertThat(op.options.containsKey("-J")).as(REMOVE).isFalse(); + assertThat(op.options().containsKey("-J")).as(REMOVE).isFalse(); } -} \ No newline at end of file +} diff --git a/src/test/resources/checkstyle-args.txt b/src/test/resources/checkstyle-args.txt new file mode 100644 index 0000000..fa76eaf --- /dev/null +++ b/src/test/resources/checkstyle-args.txt @@ -0,0 +1,16 @@ +-b +-c +-d +-e +-E +-f +-g +-j +-J +-o +-p +-s +-t +-T +-w +-x