commit b33312866097377621e5482e4ee8e63edd91eefa Author: Erik C. Thauvin Date: Sat Nov 25 14:41:22 2023 -0800 Initial commit diff --git a/.github/workflows/bld.yml b/.github/workflows/bld.yml new file mode 100644 index 0000000..d5d3f40 --- /dev/null +++ b/.github/workflows/bld.yml @@ -0,0 +1,38 @@ +name: bld-ci + +on: [ push, pull_request, workflow_dispatch ] + +jobs: + build-bld-project: + runs-on: ubuntu-latest + + strategy: + matrix: + java-version: [ 17, 20 ] + + steps: + - name: Checkout source repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up JDK ${{ matrix.java-version }} + uses: actions/setup-java@v3 + with: + distribution: 'zulu' + java-version: ${{ matrix.java-version }} + + - name: Grant execute permission for bld + run: chmod +x bld + + - name: Download the dependencies + run: ./bld download + + - name: Download the examples dependencies + run: | + cd examples + chmod +x bld + ./bld download + + - name: Run tests with bld + run: ./bld compile test diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml new file mode 100644 index 0000000..2120d4c --- /dev/null +++ b/.github/workflows/pages.yml @@ -0,0 +1,57 @@ +name: javadocs-pages + +on: + # Runs on pushes targeting the default branch + push: + branches: ["main"] + + # 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@v3 + with: + fetch-depth: 0 + + - name: Set up JDK 17 + uses: actions/setup-java@v3 + 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@v1 + with: + # Upload generated Javadocs repository + path: 'build/javadoc/' + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v1 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea86fe8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,57 @@ +.gradle +.DS_Store +build +lib/bld/** +!lib/bld/bld-wrapper.jar +!lib/bld/bld-wrapper.properties +lib/compile/ +lib/runtime/ +lib/standalone/ +lib/test/ + +# IDEA ignores + +# User-specific +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Editor-based Rest Client +.idea/httpRequests + +local.properties diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/app.iml b/.idea/app.iml new file mode 100644 index 0000000..6c0f6d7 --- /dev/null +++ b/.idea/app.iml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/bld.iml b/.idea/bld.iml new file mode 100644 index 0000000..e63e11e --- /dev/null +++ b/.idea/bld.iml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/copyright/Apache_License.xml b/.idea/copyright/Apache_License.xml new file mode 100644 index 0000000..15687f4 --- /dev/null +++ b/.idea/copyright/Apache_License.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000..f2907f1 --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..1e01b48 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/.idea/libraries/bld.xml b/.idea/libraries/bld.xml new file mode 100644 index 0000000..ca84ff0 --- /dev/null +++ b/.idea/libraries/bld.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/.idea/libraries/compile.xml b/.idea/libraries/compile.xml new file mode 100644 index 0000000..9bd86aa --- /dev/null +++ b/.idea/libraries/compile.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/runtime.xml b/.idea/libraries/runtime.xml new file mode 100644 index 0000000..2ae5c4b --- /dev/null +++ b/.idea/libraries/runtime.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/test.xml b/.idea/libraries/test.xml new file mode 100644 index 0000000..b80486a --- /dev/null +++ b/.idea/libraries/test.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..542659b --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..55adcb9 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/Run Tests.xml b/.idea/runConfigurations/Run Tests.xml new file mode 100644 index 0000000..61f1568 --- /dev/null +++ b/.idea/runConfigurations/Run Tests.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..51a77de --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "java", + "name": "Run Tests", + "request": "launch", + "mainClass": "rife.bld.extension.DetektOperationTest" + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..133aa45 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,15 @@ +{ + "java.project.sourcePaths": [ + "src/main/java", + "src/main/resources", + "src/test/java", + "src/bld/java" + ], + "java.configuration.updateBuildConfiguration": "automatic", + "java.project.referencedLibraries": [ + "${HOME}/.bld/dist/bld-1.7.5.jar", + "lib/compile/*.jar", + "lib/runtime/*.jar", + "lib/test/*.jar" + ] +} diff --git a/README.md b/README.md new file mode 100755 index 0000000..13388d9 --- /dev/null +++ b/README.md @@ -0,0 +1,45 @@ +# [bld](https://rife2.com/bld) Extension to Perform Static Code Analysis with [Detekt](https://detekt.dev/) for [Kotlin](https://kotlinlang.org/) + + +[![License](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +[![Java](https://img.shields.io/badge/java-17%2B-blue)](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html) +[![bld](https://img.shields.io/badge/1.7.3-FA9052?label=bld&labelColor=2392FF)](https://rife2.com/bld) +[![Release](https://flat.badgen.net/maven/v/metadata-url/repo.rife2.com/releases/com/uwyn/rife2/bld-detekt/maven-metadata.xml?color=blue)](https://repo.rife2.com/#/releases/com/uwyn/rife2/bld-detekt) +[![Snapshot](https://flat.badgen.net/maven/v/metadata-url/repo.rife2.com/snapshots/com/uwyn/rife2/bld-detekt/maven-metadata.xml?label=snapshot)](https://repo.rife2.com/#/snapshots/com/uwyn/rife2/bld-detekt) +[![GitHub CI](https://github.com/rife2/bld-detekt/actions/workflows/bld.yml/badge.svg)](https://github.com/rife2/bld-detekt/actions/workflows/bld.yml) + +To install, please refer to the [extensions documentation](https://github.com/rife2/bld/wiki/Extensions). + +To check all Kotlin source code located `src/main/kotlin` and `src/test/kotlin`, add the following to your build file + +```java +@BuildCommand(summary = "Check source with Detekt") +public void detekt() throws ExitStatusException, IOException, InterruptedException { + new DetektOperation() + .fromProject(this) + .execute(); +} +``` + +```console +./bld compile detekt +``` + +To generate a Detekt baseline, add the following to your build file: + +```java +@BuildCommand(value = "detekt-baseline", summary = "Creates a Detekt baseline") +public void detektBaseline() throws ExitStatusException, IOException, InterruptedException { + new DetektOperation() + .fromProject(this) + .baseline("detekt-baseline.xml") + .createBaseline(true) + .execute(); +} +``` + +```console +./bld compile detekt-baseline +``` + +Please check the [DetektOperation documentation](https://rife2.github.io/bld-detekt/rife/bld/extension/DetektOperation.html#method-summary) for all available configuration options. diff --git a/bld b/bld new file mode 100755 index 0000000..25f3b33 --- /dev/null +++ b/bld @@ -0,0 +1,2 @@ +#!/usr/bin/env sh +java -jar "$(dirname "$0")/lib/bld/bld-wrapper.jar" "$0" --build rife.bld.extension.DetektOperationBuild "$@" \ No newline at end of file diff --git a/bld.bat b/bld.bat new file mode 100644 index 0000000..66485a8 --- /dev/null +++ b/bld.bat @@ -0,0 +1,4 @@ +@echo off +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +java -jar "%DIRNAME%/lib/bld/bld-wrapper.jar" "%0" --build rife.bld.extension.DetektOperationBuild %* \ No newline at end of file diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 0000000..cf1562b --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1,57 @@ +.gradle +.DS_Store +build +lib/bld/** +!lib/bld/bld-wrapper.jar +!lib/bld/bld-wrapper.properties +lib/compile/ +lib/runtime/ +lib/standalone/ +lib/test/ + +# IDEA ignores + +# User-specific +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Editor-based Rest Client +.idea/httpRequests + +detekt-baseline.xml \ No newline at end of file diff --git a/examples/.idea/.gitignore b/examples/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/examples/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/examples/.idea/.name b/examples/.idea/.name new file mode 100644 index 0000000..2c41ed7 --- /dev/null +++ b/examples/.idea/.name @@ -0,0 +1 @@ +bld-detekt-examples \ No newline at end of file diff --git a/examples/.idea/app.iml b/examples/.idea/app.iml new file mode 100644 index 0000000..56afe0c --- /dev/null +++ b/examples/.idea/app.iml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/.idea/bld.iml b/examples/.idea/bld.iml new file mode 100644 index 0000000..2eaac76 --- /dev/null +++ b/examples/.idea/bld.iml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/.idea/inspectionProfiles/Project_Default.xml b/examples/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..1e01b48 --- /dev/null +++ b/examples/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/examples/.idea/kotlinc.xml b/examples/.idea/kotlinc.xml new file mode 100644 index 0000000..0dd4b35 --- /dev/null +++ b/examples/.idea/kotlinc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/examples/.idea/libraries/KotlinJavaRuntime.xml b/examples/.idea/libraries/KotlinJavaRuntime.xml new file mode 100644 index 0000000..215c35d --- /dev/null +++ b/examples/.idea/libraries/KotlinJavaRuntime.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/.idea/libraries/bld.xml b/examples/.idea/libraries/bld.xml new file mode 100644 index 0000000..ca84ff0 --- /dev/null +++ b/examples/.idea/libraries/bld.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/examples/.idea/libraries/compile.xml b/examples/.idea/libraries/compile.xml new file mode 100644 index 0000000..9bd86aa --- /dev/null +++ b/examples/.idea/libraries/compile.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/.idea/libraries/runtime.xml b/examples/.idea/libraries/runtime.xml new file mode 100644 index 0000000..2ae5c4b --- /dev/null +++ b/examples/.idea/libraries/runtime.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/.idea/libraries/test.xml b/examples/.idea/libraries/test.xml new file mode 100644 index 0000000..b80486a --- /dev/null +++ b/examples/.idea/libraries/test.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/.idea/misc.xml b/examples/.idea/misc.xml new file mode 100644 index 0000000..eb5c27d --- /dev/null +++ b/examples/.idea/misc.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/.idea/modules.xml b/examples/.idea/modules.xml new file mode 100644 index 0000000..55adcb9 --- /dev/null +++ b/examples/.idea/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/examples/.idea/runConfigurations/Run Tests.xml b/examples/.idea/runConfigurations/Run Tests.xml new file mode 100644 index 0000000..2b503e5 --- /dev/null +++ b/examples/.idea/runConfigurations/Run Tests.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/examples/.idea/vcs.xml b/examples/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/examples/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/examples/.vscode/launch.json b/examples/.vscode/launch.json new file mode 100644 index 0000000..30a8889 --- /dev/null +++ b/examples/.vscode/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "java", + "name": "Run Tests", + "request": "launch", + "mainClass": "com.example.ExampleTest" + } + ] +} diff --git a/examples/.vscode/settings.json b/examples/.vscode/settings.json new file mode 100644 index 0000000..133aa45 --- /dev/null +++ b/examples/.vscode/settings.json @@ -0,0 +1,15 @@ +{ + "java.project.sourcePaths": [ + "src/main/java", + "src/main/resources", + "src/test/java", + "src/bld/java" + ], + "java.configuration.updateBuildConfiguration": "automatic", + "java.project.referencedLibraries": [ + "${HOME}/.bld/dist/bld-1.7.5.jar", + "lib/compile/*.jar", + "lib/runtime/*.jar", + "lib/test/*.jar" + ] +} diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..b1926d9 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,19 @@ +j## Compile the Kotlin Example + +```console +./bld compile +``` + +## Check code with Detekt + +```console +./bld detekt +``` + +## Generate Detekt baseline + +```console +./bld detekt-baseline +``` + +The `detekt-baseline.xml` will be created in the project's root directory. diff --git a/examples/bld b/examples/bld new file mode 100755 index 0000000..80d2986 --- /dev/null +++ b/examples/bld @@ -0,0 +1,2 @@ +#!/usr/bin/env sh +java -jar "$(dirname "$0")/lib/bld/bld-wrapper.jar" "$0" --build com.example.ExampleBuild "$@" \ No newline at end of file diff --git a/examples/bld.bat b/examples/bld.bat new file mode 100644 index 0000000..084bb72 --- /dev/null +++ b/examples/bld.bat @@ -0,0 +1,4 @@ +@echo off +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +java -jar "%DIRNAME%/lib/bld/bld-wrapper.jar" "%0" --build com.example.ExampleBuild %* \ No newline at end of file diff --git a/examples/lib/bld/bld-wrapper.jar b/examples/lib/bld/bld-wrapper.jar new file mode 100644 index 0000000..250f3ea Binary files /dev/null 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 new file mode 100644 index 0000000..ba0dc11 --- /dev/null +++ b/examples/lib/bld/bld-wrapper.properties @@ -0,0 +1,8 @@ +bld.downloadExtensionJavadoc=false +bld.downloadExtensionSources=true +bld.extensions=com.uwyn.rife2:bld-kotlin:0.9.0-SNAPSHOT +bld.extension-detekt=com.uwyn.rife2:bld-detekt:0.9.0-SNAPSHOT +bld.repositories=MAVEN_LOCAL,MAVEN_CENTRAL,RIFE2_SNAPSHOTS,RIFE2_RELEASES +bld.downloadLocation= +bld.sourceDirectories= +bld.version=1.7.5 diff --git a/examples/src/bld/java/com/example/ExampleBuild.java b/examples/src/bld/java/com/example/ExampleBuild.java new file mode 100644 index 0000000..7988e55 --- /dev/null +++ b/examples/src/bld/java/com/example/ExampleBuild.java @@ -0,0 +1,85 @@ +package com.example; + +import rife.bld.BuildCommand; +import rife.bld.Project; +import rife.bld.extension.CompileKotlinOperation; +import rife.bld.extension.DetektOperation; +import rife.bld.extension.dokka.DokkaOperation; +import rife.bld.extension.dokka.LoggingLevel; +import rife.bld.extension.dokka.OutputFormat; +import rife.bld.operations.exceptions.ExitStatusException; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +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.*; +import static rife.bld.dependencies.Scope.compile; +import static rife.bld.dependencies.Scope.test; + +public class ExampleBuild extends Project { + public ExampleBuild() { + pkg = "com.example"; + name = "Example"; + mainClass = "com.example.Example"; + version = version(0, 1, 0); + + javaRelease = 17; + downloadSources = true; + autoDownloadPurge = true; + repositories = List.of(MAVEN_LOCAL, MAVEN_CENTRAL, RIFE2_RELEASES); + + scope(compile) + .include(dependency("org.jetbrains.kotlin", "kotlin-stdlib", version(1, 9, 21))); + scope(test) + .include(dependency("org.jetbrains.kotlin:kotlin-test-junit5:1.9.21")) + .include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 10, 1))) + .include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 10, 1))); + + // Include the Kotlin source directory when creating or publishing sources Java Archives + jarSourcesOperation().sourceDirectories(new File(srcMainDirectory(), "kotlin")); + } + + public static void main(String[] args) { + var level = Level.ALL; + var logger = Logger.getLogger("rife.bld.extension"); + var consoleHandler = new ConsoleHandler(); + + // Enable detailed logging for the Kotlin extension + consoleHandler.setLevel(level); + logger.addHandler(consoleHandler); + logger.setLevel(level); + logger.setUseParentHandlers(false); + + new ExampleBuild().start(args); + } + + @BuildCommand(summary = "Compile the Kotlin project") + @Override + public void compile() throws IOException { + // The source code located in src/main/kotlin and src/test/kotlin will be compiled + new CompileKotlinOperation() + .fromProject(this) + .execute(); + } + + @BuildCommand(summary = "Check source with Detekt") + public void detekt() throws ExitStatusException, IOException, InterruptedException { + new DetektOperation() + .fromProject(this) + .execute(); + } + + @BuildCommand(value = "detekt-baseline", summary = "Creates a Detekt baseline") + public void detektBaseline() throws ExitStatusException, IOException, InterruptedException { + new DetektOperation() + .fromProject(this) + .baseline("detekt-baseline.xml") + .createBaseline(true) + .execute(); + } +} \ No newline at end of file diff --git a/examples/src/main/kotlin/com/example/Example.kt b/examples/src/main/kotlin/com/example/Example.kt new file mode 100644 index 0000000..9af9aa8 --- /dev/null +++ b/examples/src/main/kotlin/com/example/Example.kt @@ -0,0 +1,34 @@ +package com.example + +import java.io.IOException + +/** + * Example class. + */ +class Example { + val message: String + get() = "Hello World!" + + // https://detekt.dev/docs/1.22.0/rules/performance#arrayprimitive + fun returningFunction(): Array { return arrayOf() } + + // https://detekt.dev/docs/1.22.0/rules/style#canbenonnullable + fun foo(a: Int?) { + val b = a!! + 2 + } + + companion object { + @JvmStatic + fun main(args: Array) { + // https://detekt.dev/docs/1.22.0/rules/naming#booleanpropertynaming + val progressBar: Boolean = true + // https://detekt.dev/docs/1.22.0/rules/potential-bugs#avoidreferentialequality + val areEqual = "aString" === "" + println(Example().message) + if (false) { + // https://detekt.dev/docs/1.22.0/rules/exceptions#exceptionraisedinunexpectedlocation + throw IllegalStateException() + } + } + } +} diff --git a/examples/src/test/kotlin/com/example/ExampleTest.kt b/examples/src/test/kotlin/com/example/ExampleTest.kt new file mode 100644 index 0000000..e8c53ae --- /dev/null +++ b/examples/src/test/kotlin/com/example/ExampleTest.kt @@ -0,0 +1,11 @@ +package com.example + +import kotlin.test.Test +import kotlin.test.assertEquals + +class ExampleTest { + @Test + fun verifyHello() { + assertEquals("Hello World!", Example().message) + } +} // https://detekt.dev/docs/1.22.0/rules/empty-blocks#emptyfunctionblock \ No newline at end of file diff --git a/lib/bld/bld-wrapper.jar b/lib/bld/bld-wrapper.jar new file mode 100644 index 0000000..9545010 Binary files /dev/null and b/lib/bld/bld-wrapper.jar differ diff --git a/lib/bld/bld-wrapper.properties b/lib/bld/bld-wrapper.properties new file mode 100644 index 0000000..1eff7d0 --- /dev/null +++ b/lib/bld/bld-wrapper.properties @@ -0,0 +1,7 @@ +bld.downloadExtensionJavadoc=false +bld.downloadExtensionSources=true +bld.extension-jacoco=com.uwyn.rife2:bld-jacoco-report:0.9.1 +bld.repositories=MAVEN_LOCAL,MAVEN_CENTRAL,RIFE2_SNAPSHOTS,RIFE2_RELEASES +bld.downloadLocation= +bld.sourceDirectories= +bld.version=1.7.5 diff --git a/src/bld/java/rife/bld/extension/DetektOperationBuild.java b/src/bld/java/rife/bld/extension/DetektOperationBuild.java new file mode 100644 index 0000000..42ddb5f --- /dev/null +++ b/src/bld/java/rife/bld/extension/DetektOperationBuild.java @@ -0,0 +1,96 @@ +/* + * Copyright 2023 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; + +import rife.bld.Project; +import rife.bld.publish.PublishDeveloper; +import rife.bld.publish.PublishLicense; +import rife.bld.publish.PublishScm; + +import java.util.List; + +import static rife.bld.dependencies.Repository.MAVEN_CENTRAL; +import static rife.bld.dependencies.Repository.RIFE2_RELEASES; +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 DetektOperationBuild extends Project { + public DetektOperationBuild() { + pkg = "rife.bld.extension"; + name = "DetektOperation"; + version = version(0, 9, 0, "SNAPSHOT"); + + javaRelease = 17; + downloadSources = true; + autoDownloadPurge = true; + repositories = List.of(MAVEN_CENTRAL, RIFE2_RELEASES); + + scope(compile) + .include(dependency("com.uwyn.rife2", "bld", version(1, 7, 5))) + .include(dependency("io.gitlab.arturbosch.detekt", "detekt-cli", version(1, 23, 3))) +// .include(dependency("io.gitlab.arturbosch.detekt", "detekt-core", version(1, 23, 3))) +// .include(dependency("io.gitlab.arturbosch.detekt", "detekt-rules", version(1, 23, 3))) +// .include(dependency("io.gitlab.arturbosch.detekt", "detekt-utils", version(1, 23, 3))) + .include(dependency("io.gitlab.arturbosch.detekt", "detekt-tooling", version(1, 23, 3))) + .include(dependency("com.beust", "jcommander", "1.82")) + .include(dependency("com.fasterxml:aalto-xml:1.3.2")); + scope(test) + .include(dependency("com.puppycrawl.tools", "checkstyle", version(10, 12, 5))) + .include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 10, 1))) + .include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 10, 1))) + .include(dependency("org.assertj", "assertj-core", version(3, 24, 2))); + 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")) + .info() + .groupId("com.uwyn.rife2") + .artifactId("bld-detekt") + .description("bld Detekt Extension") + .url("https://github.com/rife2/bld-detekt") + .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-detekt.git") + .developerConnection("scm:git:git@github.com:rife2/bld-detekt.git") + .url("https://github.com/rife2/bld-detekt") + ) + .signKey(property("sign.key")) + .signPassphrase(property("sign.passphrase")); + } + + public static void main(String[] args) { + new DetektOperationBuild().start(args); + } +} \ No newline at end of file diff --git a/src/main/java/rife/bld/extension/DetektOperation.java b/src/main/java/rife/bld/extension/DetektOperation.java new file mode 100644 index 0000000..882d460 --- /dev/null +++ b/src/main/java/rife/bld/extension/DetektOperation.java @@ -0,0 +1,552 @@ +/* + * Copyright 2023 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; + +import rife.bld.BaseProject; +import rife.bld.operations.AbstractProcessOperation; + +import java.io.File; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Performs static code analysis with Detekt. + * + * @author Erik C. Thauvin + * @since 1.0 + */ +public class DetektOperation extends AbstractProcessOperation { + private static final Logger LOGGER = Logger.getLogger(DetektReport.class.getName()); + private final Collection classpath_ = new ArrayList<>(); + private final Collection config_ = new ArrayList<>(); + private final Collection input_ = new ArrayList<>(); + private final Collection plugins_ = new ArrayList<>(); + private final Collection report_ = new ArrayList<>(); + private boolean allRules_ = false; + private boolean autoCorrect_ = false; + private String basePath_; + private String baseline_; + private boolean buildUponDefaultConfig_; + private String configResource_; + private boolean createBaseline_; + private boolean debug_ = false; + private boolean disableDefaultRuleSets_ = false; + private String excludes_; + private boolean generateConfig_; + private String includes_; + private String jdkHome_; + private String jvmTarget_; + private String languageVersion_; + private int maxIssues_; + private boolean parallel_; + private BaseProject project_; + + /** + * Activates all available (even unstable) rules. + * + * @param allRules {@code true} or {@code false} + * @return this operation instance + */ + public DetektOperation allRules(boolean allRules) { + allRules_ = allRules; + return this; + } + + /** + * Allow rules to auto correct code if they support it. The default rule + * sets do NOT support auto correcting and won't change any line in the + * users code base. However custom rules can be written to support auto + * correcting. The additional 'formatting' rule set, added with + * {@link #plugins(String...) Plugins}, does support it and needs this flag. + * + * @param autoCorrect {@code true} or {@code false} + * @return this operation instance + */ + public DetektOperation autoCorrect(boolean autoCorrect) { + autoCorrect_ = autoCorrect; + return this; + } + + /** + * Specifies a directory as the base path. Currently it impacts all file + * paths in the formatted reports. File paths in console output and txt + * report are not affected and remain as absolute paths. + * + * @param path the directory path + * @return this operation instance + */ + public DetektOperation basePath(String path) { + basePath_ = path; + return this; + } + + /** + * If a baseline xml file is passed in, only new code smells not in the + * baseline are printed in the console. + * + * @param baseline the baseline xml file + * @return this operation instance + */ + public DetektOperation baseline(String baseline) { + baseline_ = baseline; + return this; + } + + /** + * Preconfigures detekt with a bunch of rules and some opinionated defaults + * for you. Allows additional provided configurations to override the + * defaults. + * + * @param buildUponDefaultConfig {@code true} or {@code false} + * @return this operation instance + */ + public DetektOperation buildUponDefaultConfig(boolean buildUponDefaultConfig) { + buildUponDefaultConfig_ = buildUponDefaultConfig; + return this; + } + + /** + * EXPERIMENTAL: Paths where to find user class files and depending jar + * files. Used for type resolution. + * + * @param paths one or more files + * @return this operation instance + */ + public DetektOperation classPath(String... paths) { + classpath_.addAll(List.of(paths)); + return this; + } + + /** + * EXPERIMENTAL: Paths where to find user class files and depending jar + * files. Used for type resolution. + * + * @param paths the list of files + * @return this operation instance + */ + public DetektOperation classPath(Collection paths) { + classpath_.addAll(paths); + return this; + } + + /** + * Path to the config file ({@code path/to/config.yml}). + * + * @param configs one or more config files + * @return this operation instance + */ + public DetektOperation config(String... configs) { + config_.addAll(List.of(configs)); + return this; + } + + /** + * Path to the config file ({@code path/to/config.yml}). + * + * @param configs the list pf config files + * @return this operation instance + */ + public DetektOperation config(Collection configs) { + config_.addAll(configs); + return this; + } + + /** + * Path to the config resource on detekt's classpath ({@code path/to/config.yml}). + * + * @param resource the config resource path + * @return this operation instance + */ + public DetektOperation configResource(String resource) { + configResource_ = resource; + return this; + } + + /** + * Treats current analysis findings as a smell baseline for future detekt + * runs. + * + * @param createBaseline {@code true} or {@code false} + * @return this operation instance + */ + public DetektOperation createBaseline(boolean createBaseline) { + createBaseline_ = createBaseline; + return this; + } + + /** + * Prints extra information about configurations and extensions. + * + * @param debug {@code true} or {@code false} + * @return this operation instance + */ + public DetektOperation debug(boolean debug) { + debug_ = debug; + return this; + } + + /** + * Disables default rule sets. + * + * @param disable {@code true} or {@code false} + * @return this operation instance + */ + public DetektOperation disableDefaultRuleSets(boolean disable) { + disableDefaultRuleSets_ = disable; + return this; + } + + /** + * Globbing patterns describing paths to exclude from the analysis. + * + * @param patterns the patterns + * @return this operation instance + */ + public DetektOperation excludes(String patterns) { + excludes_ = patterns; + return this; + } + + /** + * 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."); + } + + final List args = new ArrayList<>(); + args.add(javaTool()); + args.add("-cp"); + args.add(Path.of(project_.libBldDirectory().getAbsolutePath(), "*").toString()); + args.add("io.gitlab.arturbosch.detekt.cli.Main"); + + // all-rules + if (allRules_) { + args.add("--all-rules"); + } + + // auto-correct + if (autoCorrect_) { + args.add("--auto-correct"); + } + + // base-path + if (basePath_ != null) { + args.add("--base-path"); + args.add(basePath_); + } + + // baseline + if (baseline_ != null) { + args.add("--baseline"); + args.add(baseline_); + } + + // build-upon-default-config + if (buildUponDefaultConfig_) { + args.add("--build-upon-default-config"); + } + + // classpath + if (!classpath_.isEmpty()) { + args.add("--classpath"); + args.add(String.join(File.pathSeparator, classpath_)); + } + + // config + if (!config_.isEmpty()) { + args.add("-config"); + args.add(String.join(";", config_)); + } + + // config-resource + if (configResource_ != null) { + args.add("--config-resource"); + args.add(configResource_); + } + + // create-baseline + if (createBaseline_) { + args.add("--create-baseline"); + } + + // debug + if (debug_) { + args.add("--debug"); + } + + // disable-default-rulesets + if (disableDefaultRuleSets_) { + args.add("--disable-default-rulesets"); + } + + // excludes + if (excludes_ != null) { + args.add("--excludes"); + + } + + // generate-config + if (generateConfig_) { + args.add("--generate-config"); + } + + // includes + if (includes_ != null) { + args.add("--includes"); + args.add(includes_); + } + + // input + if (!input_.isEmpty()) { + args.add("--input"); + args.add(String.join(",", input_)); + } + + // jdk-home + if (jdkHome_ != null) { + args.add("--jdk-home"); + args.add(jdkHome_); + } + + // jvm-target + if (jvmTarget_ != null) { + args.add("--jvm-target"); + args.add(jvmTarget_); + } + + // language-version + if (languageVersion_ != null) { + args.add("--language-version"); + args.add(languageVersion_); + } + + // max-issues + if (maxIssues_ > 0) { + args.add("--max-issues"); + args.add(String.valueOf(maxIssues_)); + } + + // parallel + if (parallel_) { + args.add("--parallel"); + } + + // plugins + if (!plugins_.isEmpty()) { + args.add("--plugins"); + args.add(String.join(".", plugins_)); + } + + // report + if (!report_.isEmpty()) { + report_.forEach(it -> { + args.add("-r"); + args.add(it.id().name().toLowerCase() + ":" + it.path()); + }); + } + + if (LOGGER.isLoggable(Level.FINE)) { + LOGGER.fine(String.join(" ", args)); + } + + return args; + } + + /** + * Configures the operation from a {@link BaseProject}. + *

+ * Sets the {@link #input input} to {@code src/main/kotlin}, {@code src/test/kotlin} and {@code detekt-baseline.xml} + * if they exist. + * + * @param project the project to configure the operation from + * @return this operation instance + */ + @Override + public DetektOperation fromProject(BaseProject project) { + project_ = project; + var main = new File(project.srcMainDirectory(), "kotlin"); + if (main.exists()) { + input_.add(main.getAbsolutePath()); + } + var test = new File(project.srcTestDirectory(), "kotlin"); + if (test.exists()) { + input_.add(test.getAbsolutePath()); + } + var baseline = new File(project.workDirectory(), "detekt-baseline.xml"); + if (baseline.exists()) { + baseline_ = baseline.getAbsolutePath(); + } + return this; + } + + /** + * Export default config. Path can be specified with {@link #config config} option. + *

+ * Default path: {@code default-detekt-config.yml} + * + * @param generate {@code true} or {@code false} + * @return this operation instance + */ + public DetektOperation generateConfig(boolean generate) { + generateConfig_ = generate; + return this; + } + + /** + * Globbing patterns describing paths to include in the analysis. Useful in + * combination with {@link #excludes(String) excludes} patterns. + * + * @param patterns the patterns + * @return this operation instance + */ + public DetektOperation includes(String patterns) { + includes_ = patterns; + return this; + } + + /** + * Input paths to analyze. If not specified the current working directory is used. + * + * @param paths the list of paths + * @return this operation instance + */ + public DetektOperation input(Collection paths) { + input_.addAll(paths); + return this; + } + + /** + * Input paths to analyze. If not specified the current working directory is used. + * + * @param paths one or more paths + * @return this operation instance + */ + public DetektOperation input(String... paths) { + input_.addAll(List.of(paths)); + return this; + } + + /** + * EXPERIMENTAL: Use a custom JDK home directory to include into the + * classpath. + * + * @param path the JDK home directory path + * @return this operation instance + */ + public DetektOperation jdkHome(String path) { + jdkHome_ = path; + return this; + } + + /** + * EXPERIMENTAL: Target version of the generated JVM bytecode that was + * generated during compilation and is now being used for type resolution + *

+ * Default: 1.8 + * + * @param target the target version + * @return this operation instance + */ + public DetektOperation jvmTarget(String target) { + jvmTarget_ = target; + return this; + } + + /** + * EXPERIMENTAL: Compatibility mode for Kotlin language version X.Y, + * reports errors for all language features that came out later. + *

+ * Possible Values: [1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1] + * + * @param version the version + * @return this operation instance + */ + public DetektOperation languageVersion(String version) { + languageVersion_ = version; + return this; + } + + /** + * Return exit code 0 only when found issues count does not exceed + * specified issues count. + * + * @param max the issues code + * @return this operation instance + */ + public DetektOperation maxIssues(int max) { + maxIssues_ = max; + return this; + } + + /** + * Enables parallel compilation and analysis of source files. Do some + * benchmarks first before enabling this flag. Heuristics show performance + * benefits starting from 2000 lines of Kotlin code. + * + * @param parallel{@code true} or {@code false} + * @return this operation instance + */ + public DetektOperation parallel(boolean parallel) { + parallel_ = parallel; + return this; + } + + /** + * Enables parallel compilation and analysis of source files. Do some + * benchmarks first before enabling this flag. Heuristics show performance + * benefits starting from 2000 lines of Kotlin code. + * + * @param jars one or more jars + * @return this operation instance + */ + public DetektOperation plugins(String... jars) { + plugins_.addAll(List.of(jars)); + return this; + } + + /** + * Enables parallel compilation and analysis of source files. Do some + * benchmarks first before enabling this flag. Heuristics show performance + * benefits starting from 2000 lines of Kotlin code. + * + * @param jars the list of jars + * @return this operation instance + */ + public DetektOperation plugins(Collection jars) { + plugins_.addAll(jars); + return this; + } + + /** + * Generates a report for given 'report-id' and stores it on given 'path'. + * + * @param reports one or more reports + * @return this operation instance + */ + public DetektOperation report(DetektReport... reports) { + report_.addAll(List.of(reports)); + return this; + } +} \ No newline at end of file diff --git a/src/main/java/rife/bld/extension/DetektReport.java b/src/main/java/rife/bld/extension/DetektReport.java new file mode 100644 index 0000000..e21eefb --- /dev/null +++ b/src/main/java/rife/bld/extension/DetektReport.java @@ -0,0 +1,28 @@ +/* + * Copyright 2023 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; + +/** + * Defines a report for given report-id to be stores in the given path. + * + * @param id the report-id + * @param path the given path + * @author Erik C. Thauvin + * @since 1.0 + */ +public record DetektReport(DetektReportId id, String path) { +} diff --git a/src/main/java/rife/bld/extension/DetektReportId.java b/src/main/java/rife/bld/extension/DetektReportId.java new file mode 100644 index 0000000..4f074ce --- /dev/null +++ b/src/main/java/rife/bld/extension/DetektReportId.java @@ -0,0 +1,27 @@ +/* + * Copyright 2023 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; + +/** + * The report-id values. + * + * @author Erik C. Thauvin + * @since 1.0 + */ +public enum DetektReportId { + TXT, XML, HTML, MD, SARIF +} diff --git a/src/test/java/rife/bld/extension/DetektOperationTest.java b/src/test/java/rife/bld/extension/DetektOperationTest.java new file mode 100644 index 0000000..0cf4551 --- /dev/null +++ b/src/test/java/rife/bld/extension/DetektOperationTest.java @@ -0,0 +1,104 @@ +/* + * Copyright 2023 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; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import rife.bld.blueprints.BaseProjectBlueprint; +import rife.bld.operations.exceptions.ExitStatusException; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +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.*; + + +class DetektOperationTest { + @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 testExamplesExecute() { + var op = new DetektOperation() + .fromProject(new BaseProjectBlueprint(new File("examples"), "com.example", + "Example")); + assertThatThrownBy(op::execute).isInstanceOf(ExitStatusException.class); + } + + @Test + void testExampleMaxIssues() { + var op = new DetektOperation() + .fromProject(new BaseProjectBlueprint(new File("examples"), "com.example", + "Example")) + .maxIssues(8); + assertThatNoException().isThrownBy(op::execute); + } + + @Test + void testExampleReports() throws IOException { + var tmpDir = Files.createTempDirectory("bld-detekt-").toFile(); + tmpDir.deleteOnExit(); + + var html = new File(tmpDir, "report.html"); + var xml = new File(tmpDir, "report.xml"); + var txt = new File(tmpDir, "report.txt"); + var md = new File(tmpDir, "report.md"); + var sarif = new File(tmpDir, "report.sarif"); + + var op = new DetektOperation() + .fromProject(new BaseProjectBlueprint(new File("examples"), "com.example", + "Example")) + .report(new DetektReport(DetektReportId.HTML, html.getAbsolutePath())) + .report(new DetektReport(DetektReportId.XML, xml.getAbsolutePath())) + .report(new DetektReport(DetektReportId.TXT, txt.getAbsolutePath())) + .report(new DetektReport(DetektReportId.MD, md.getAbsolutePath())) + .report(new DetektReport(DetektReportId.SARIF, sarif.getAbsolutePath())); + + assertThatThrownBy(op::execute).isInstanceOf(ExitStatusException.class); + + List.of(html, xml, txt, md, sarif).forEach(it -> assertThat(it).exists()); + } + + @Test + void testExampleBaseline() throws IOException, ExitStatusException, InterruptedException { + var tmpDir = Files.createTempDirectory("bld-detekt-").toFile(); + tmpDir.deleteOnExit(); + + var baseline = new File(tmpDir, "detekt-baseline.xml"); + + var op = new DetektOperation() + .fromProject(new BaseProjectBlueprint(new File("examples"), "com.example", + "Example")) + .baseline(baseline.getAbsolutePath()) + .createBaseline(true); + op.execute(); + assertThat(baseline).exists(); + } +} \ No newline at end of file