diff --git a/.github/workflows/bld.yml b/.github/workflows/bld.yml index cfed82f..99d5cec 100644 --- a/.github/workflows/bld.yml +++ b/.github/workflows/bld.yml @@ -4,36 +4,47 @@ on: [ push, pull_request, workflow_dispatch ] jobs: build-bld-project: + runs-on: ubuntu-latest + strategy: matrix: - 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 }} + java-version: [ 17, 20 ] steps: - name: Checkout source repository - uses: actions/checkout@v4 + uses: actions/checkout@v3 with: fetch-depth: 0 - name: Set up JDK ${{ matrix.java-version }} - uses: actions/setup-java@v4 + uses: actions/setup-java@v3 with: - distribution: "zulu" + distribution: 'zulu' java-version: ${{ matrix.java-version }} - - name: Download dependencies [examples] + - name: Download the examples dependencies working-directory: examples - run: ./bld download + run: | + chmod +x bld + ./bld download - - name: Run tests [examples] + - name: Run examples tests working-directory: examples run: ./bld compile test - - name: Download dependencies + - name: Build examples documentation + working-directory: examples + run : | + ./bld javadoc + ./bld dokka-html + ./bld dokka-gfm + ./bld dokka-jekyll + + - name: Grant execute permission for bld + run: chmod +x bld + + - name: Download the dependencies run: ./bld download - name: Run tests - run: ./bld compile test \ No newline at end of file + run: ./bld compile pmd test diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index e864e62..2120d4c 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -3,7 +3,7 @@ name: javadocs-pages on: # Runs on pushes targeting the default branch push: - branches: [ "main" ] + branches: ["main"] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: @@ -30,14 +30,14 @@ jobs: steps: - name: Checkout source repository - uses: actions/checkout@v4 + uses: actions/checkout@v3 with: fetch-depth: 0 - name: Set up JDK 17 - uses: actions/setup-java@v4 + uses: actions/setup-java@v3 with: - distribution: "zulu" + distribution: 'zulu' java-version: 17 - name: Build Javadocs @@ -47,11 +47,11 @@ jobs: uses: actions/configure-pages@v3 - name: Upload artifact - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@v1 with: # Upload generated Javadocs repository - path: "build/javadoc/" + path: 'build/javadoc/' - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@v1 \ No newline at end of file diff --git a/.idea/bld.xml b/.idea/bld.xml deleted file mode 100644 index 6600cee..0000000 --- a/.idea/bld.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index d91f848..0000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/copyright/Apache_License.xml b/.idea/copyright/Apache_License.xml index 4446c15..ade80da 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 deleted file mode 100644 index 81220b4..0000000 --- a/.idea/icon.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.idea/libraries/bld.xml b/.idea/libraries/bld.xml index f9b1d1d..effc236 100644 --- a/.idea/libraries/bld.xml +++ b/.idea/libraries/bld.xml @@ -2,12 +2,12 @@ - + - + diff --git a/.idea/libraries/compile.xml b/.idea/libraries/compile.xml index 99cc0c0..9bd86aa 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 d4069f2..2ae5c4b 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 57ed5ef..b80486a 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 593e427..b386dc0 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,21 +1,7 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/examples/.idea/libraries/bld.xml b/examples/.idea/libraries/bld.xml index 153a060..bff4f62 100644 --- a/examples/.idea/libraries/bld.xml +++ b/examples/.idea/libraries/bld.xml @@ -2,12 +2,12 @@ - + - + diff --git a/examples/.idea/libraries/compile.xml b/examples/.idea/libraries/compile.xml index 99cc0c0..9bd86aa 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 d4069f2..2ae5c4b 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 57ed5ef..b80486a 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 70c470c..78b0f96 100644 --- a/examples/.idea/misc.xml +++ b/examples/.idea/misc.xml @@ -1,3 +1,4 @@ + @@ -23,7 +24,4 @@ - - \ No newline at end of file diff --git a/examples/.vscode/launch.json b/examples/.vscode/launch.json index 6fe9188..30a8889 100644 --- a/examples/.vscode/launch.json +++ b/examples/.vscode/launch.json @@ -5,11 +5,7 @@ "type": "java", "name": "Run Tests", "request": "launch", - "mainClass": "com.example.ExampleBuild", - "args": [ - "compile", - "test" - ] + "mainClass": "com.example.ExampleTest" } ] -} \ No newline at end of file +} diff --git a/examples/.vscode/settings.json b/examples/.vscode/settings.json index ba429d0..5633e79 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/test/resources", - "src/bld/java", - "src/bld/resources" + "src/bld/java" ], "java.configuration.updateBuildConfiguration": "automatic", "java.project.referencedLibraries": [ - "${HOME}/.bld/dist/bld-2.2.1.jar", - "lib/**/*.jar" + "${HOME}/.bld/dist/bld-1.8.0.jar", + "lib/compile/*.jar", + "lib/runtime/*.jar", + "lib/test/*.jar" ] } diff --git a/examples/README.md b/examples/README.md index b22a8f1..1dbc9fb 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,3 +1,4 @@ + ## Compile the Kotlin Example ```console @@ -16,6 +17,11 @@ ./bld test ``` -## Requirements +## Build the documentation with [Dokka](https://github.com/Kotlin/dokka) -- A Kotlin compiler must be [installed](https://github.com/rife2/bld-kotlin?tab=readme-ov-file#kotlin-compiler-requirement). +```console +./bld javadoc +./bld dokka-html +./bld dokka-gfm +./bld dokka-jekyll +``` diff --git a/examples/lib/bld/bld-wrapper.jar b/examples/lib/bld/bld-wrapper.jar index 06cf59e..cc3d9e7 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 1f1009d..600e985 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.downloadLocation= -bld.extension-kotlin=com.uwyn.rife2:bld-kotlin:1.1.0-SNAPSHOT +bld.extensions=com.uwyn.rife2:bld-kotlin:0.9.0 bld.repositories=MAVEN_LOCAL,MAVEN_CENTRAL,RIFE2_SNAPSHOTS,RIFE2_RELEASES +bld.downloadLocation= bld.sourceDirectories= -bld.version=2.2.1 +bld.version=1.8.0 diff --git a/examples/src/bld/java/com/example/ExampleBuild.java b/examples/src/bld/java/com/example/ExampleBuild.java index 170c5b5..432e0ce 100644 --- a/examples/src/bld/java/com/example/ExampleBuild.java +++ b/examples/src/bld/java/com/example/ExampleBuild.java @@ -3,10 +3,14 @@ package com.example; import rife.bld.BuildCommand; import rife.bld.Project; import rife.bld.extension.CompileKotlinOperation; -import rife.bld.extension.kotlin.CompileOptions; -import rife.bld.extension.kotlin.JvmOptions; +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; @@ -24,20 +28,17 @@ public class ExampleBuild extends Project { version = version(0, 1, 0); javaRelease = 17; - downloadSources = true; autoDownloadPurge = true; - repositories = List.of(MAVEN_LOCAL, MAVEN_CENTRAL, RIFE2_RELEASES); - final var kotlin = version(2, 1, 20); + final var kotlin = version(1, 9, 22); scope(compile) .include(dependency("org.jetbrains.kotlin", "kotlin-stdlib", kotlin)); scope(test) .include(dependency("org.jetbrains.kotlin", "kotlin-test-junit5", kotlin)) - .include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 12, 2))) - .include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 12, 2))) - .include(dependency("org.junit.platform", "junit-platform-launcher", version(1, 12, 2))); + .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")); @@ -45,27 +46,73 @@ public class ExampleBuild extends Project { public static void main(String[] args) { // Enable detailed logging for the Kotlin extension - var level = Level.ALL; - var logger = Logger.getLogger("rife.bld.extension"); - var consoleHandler = new ConsoleHandler(); + // 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); + // consoleHandler.setLevel(level); + // logger.addHandler(consoleHandler); + // logger.setLevel(level); + // logger.setUseParentHandlers(false); new ExampleBuild().start(args); } @BuildCommand(summary = "Compiles the Kotlin project") @Override - public void compile() throws Exception { + public void compile() throws IOException { // The source code located in src/main/kotlin and src/test/kotlin will be compiled new CompileKotlinOperation() -// .kotlinHome("path/to/kotlin") -// .kotlinc("path/to/kotlinc") - .compileOptions(new CompileOptions().verbose(true)) .fromProject(this) .execute(); + +// var op = new CompileKotlinOperation().fromProject(this); +// op.compileOptions().verbose(true); +// op.execute(); } -} + + @BuildCommand(value = "dokka-gfm", summary = "Generates documentation in GitHub flavored markdown format") + public void dokkaGfm() throws ExitStatusException, IOException, InterruptedException { + new DokkaOperation() + .fromProject(this) + .loggingLevel(LoggingLevel.INFO) + // Create build/dokka/gfm + .outputDir(Path.of(buildDirectory().getAbsolutePath(), "dokka", "gfm").toFile()) + .outputFormat(OutputFormat.MARKDOWN) + .execute(); + } + + @BuildCommand(value = "dokka-html", summary = "Generates documentation in HTML format") + public void dokkaHtml() throws ExitStatusException, IOException, InterruptedException { + new DokkaOperation() + .fromProject(this) + .loggingLevel(LoggingLevel.INFO) + // Create build/dokka/html + .outputDir(Path.of(buildDirectory().getAbsolutePath(), "dokka", "html").toFile()) + .outputFormat(OutputFormat.HTML) + .execute(); + } + + @BuildCommand(value = "dokka-jekyll", summary = "Generates documentation in Jekyll flavored markdown format") + public void dokkaJekyll() throws ExitStatusException, IOException, InterruptedException { + new DokkaOperation() + .fromProject(this) + .loggingLevel(LoggingLevel.INFO) + // Create build/dokka/jekyll + .outputDir(Path.of(buildDirectory().getAbsolutePath(), "dokka", "jekkyl").toFile()) + .outputFormat(OutputFormat.JEKYLL) + .execute(); + } + + @BuildCommand(summary = "Generates Javadoc for the project") + @Override + public void javadoc() throws ExitStatusException, IOException, InterruptedException { + new DokkaOperation() + .fromProject(this) + .loggingLevel(LoggingLevel.INFO) + // Create build/javadoc + .outputDir(new File(buildDirectory(), "javadoc")) + .outputFormat(OutputFormat.JAVADOC) + .execute(); + } +} \ No newline at end of file diff --git a/lib/bld/bld-wrapper.jar b/lib/bld/bld-wrapper.jar index d7879eb..cc3d9e7 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 d29a55f..131b200 100644 --- a/lib/bld/bld-wrapper.properties +++ b/lib/bld/bld-wrapper.properties @@ -1,10 +1,7 @@ bld.downloadExtensionJavadoc=false bld.downloadExtensionSources=true +bld.extension-pmd=com.uwyn.rife2:bld-pmd:0.9.5 +bld.repositories=MAVEN_CENTRAL,RIFE2_RELEASES bld.downloadLocation= -bld.javaOptions= -bld.javacOptions= -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=2.2.1 +bld.version=1.8.0 diff --git a/scripts/checkcliargs.sh b/scripts/checkcliargs.sh deleted file mode 100755 index 94313ab..0000000 --- a/scripts/checkcliargs.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -new=/tmp/checkcliargs-new -old=/tmp/checkcliargs-old - -kotlinc -h 2>$new -~/.sdkman/candidates/kotlin/2.1.10/bin/kotlinc -h 2>$old - -code --diff --wait $old $new - -rm -rf $new $old diff --git a/scripts/cliargs.sh b/scripts/cliargs.sh deleted file mode 100755 index bb433c2..0000000 --- a/scripts/cliargs.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -kotlinc -h 2> >(grep "^ ") | - sed -e "s/^ //" -e "s/ .*//" -e "s/<.*//" -e '/-help/d' -e '/^-version/d' -e '/^$/d' | - sort >"src/test/resources/kotlinc-args.txt" diff --git a/src/bld/java/rife/bld/extension/CompileKotlinOperationBuild.java b/src/bld/java/rife/bld/extension/CompileKotlinOperationBuild.java index 53e84c7..4b5b522 100644 --- a/src/bld/java/rife/bld/extension/CompileKotlinOperationBuild.java +++ b/src/bld/java/rife/bld/extension/CompileKotlinOperationBuild.java @@ -1,5 +1,5 @@ /* - * Copyright 2023-2025 the original author or authors. + * Copyright 2023-2024 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. @@ -23,7 +23,6 @@ import rife.bld.publish.PublishLicense; import rife.bld.publish.PublishScm; import java.util.List; -import java.util.Locale; import static rife.bld.dependencies.Repository.*; import static rife.bld.dependencies.Scope.compile; @@ -34,21 +33,30 @@ public class CompileKotlinOperationBuild extends Project { public CompileKotlinOperationBuild() { pkg = "rife.bld.extension"; name = "bld-kotlin"; - version = version(1, 1, 0, "SNAPSHOT"); + version = version(0, 9, 0); javaRelease = 17; - downloadSources = true; autoDownloadPurge = true; + repositories = List.of(MAVEN_LOCAL, MAVEN_CENTRAL, RIFE2_RELEASES); - repositories = List.of(MAVEN_LOCAL, MAVEN_CENTRAL, RIFE2_RELEASES, RIFE2_SNAPSHOTS); - + var dokka = version(1, 9, 10); + var kotlin = version(1, 9, 22); scope(compile) - .include(dependency("com.uwyn.rife2", "bld", version(2, 2, 1))); + .include(dependency("org.jetbrains.kotlin", "kotlin-compiler", kotlin)) + .include(dependency("org.jetbrains.kotlin", "kotlin-annotation-processing", kotlin)) + .include(dependency("org.jetbrains.kotlin", "kotlin-scripting-compiler", kotlin)) + .include(dependency("org.jetbrains.dokka", "dokka-cli", dokka)) + .include(dependency("org.jetbrains.dokka", "dokka-base", dokka)) + .include(dependency("org.jetbrains.dokka", "analysis-kotlin-descriptors", dokka)) + .include(dependency("org.jetbrains.dokka", "javadoc-plugin", dokka)) + .include(dependency("org.jetbrains.dokka", "gfm-plugin", dokka)) + .include(dependency("org.jetbrains.dokka", "jekyll-plugin", dokka)) + .include(dependency("com.uwyn.rife2", "bld", version(1, 8, 0))); scope(test) - .include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 12, 2))) - .include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 12, 2))) - .include(dependency("org.assertj", "assertj-core", version(3, 27, 3))); + .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, 25, 2))); javadocOperation() .javadocOptions() @@ -58,26 +66,28 @@ public class CompileKotlinOperationBuild extends Project { publishOperation() .repository(version.isSnapshot() ? repository("rife2-snapshot") : repository("rife2")) - .repository(repository("github")) .info() .groupId("com.uwyn.rife2") .artifactId("bld-kotlin") .description("bld Kotlin Extension") .url("https://github.com/rife2/bld-kotlin") - .developer(new PublishDeveloper() - .id("ethauvin") - .name("Erik C. Thauvin") - .email("erik@thauvin.net") - .url("https://erik.thauvin.net/") + .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") + .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-kotlin.git") - .developerConnection("scm:git:git@github.com:rife2/bld-kotlin.git") - .url("https://github.com/rife2/bld-kotlin") + .scm( + new PublishScm() + .connection("scm:git:https://github.com/rife2/bld-kotlin.git") + .developerConnection("scm:git:git@github.com:rife2/bld-kotlin.git") + .url("https://github.com/rife2/bld-kotlin") ) .signKey(property("sign.key")) .signPassphrase(property("sign.passphrase")); @@ -88,23 +98,11 @@ public class CompileKotlinOperationBuild extends Project { } @BuildCommand(summary = "Runs PMD analysis") - public void pmd() throws Exception { + public void pmd() { 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/CompileKotlinOperation.java b/src/main/java/rife/bld/extension/CompileKotlinOperation.java index 5932298..1465991 100644 --- a/src/main/java/rife/bld/extension/CompileKotlinOperation.java +++ b/src/main/java/rife/bld/extension/CompileKotlinOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2023-2025 the original author or authors. + * Copyright 2023-2024 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,21 +16,17 @@ package rife.bld.extension; +import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler; import rife.bld.BaseProject; -import rife.bld.extension.kotlin.CompileOptions; -import rife.bld.extension.kotlin.CompilerPlugin; -import rife.bld.extension.kotlin.JvmOptions; import rife.bld.operations.AbstractOperation; -import rife.bld.operations.exceptions.ExitStatusException; import rife.tools.FileUtils; import java.io.File; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.regex.Pattern; /** * Compiles main and test Kotlin sources in the relevant build directories. @@ -39,13 +35,13 @@ import java.util.logging.Logger; * @since 1.0 */ public class CompileKotlinOperation extends AbstractOperation { + /** + * The Kotlin file (.kt) pattern. + */ + public static final Pattern KOTLIN_FILE_PATTERN = Pattern.compile("^.*\\.kt$"); private static final Logger LOGGER = Logger.getLogger(CompileKotlinOperation.class.getName()); - private static final String OS_NAME = - System.getProperty("os.name") != null ? System.getProperty("os.name").toLowerCase(Locale.US) : null; - private static final String KOTLINC_EXECUTABLE = "kotlinc" + (isWindows() ? ".bat" : ""); private final Collection compileMainClasspath_ = new ArrayList<>(); private final Collection compileTestClasspath_ = new ArrayList<>(); - private final JvmOptions jvmOptions_ = new JvmOptions(); private final Collection mainSourceDirectories_ = new ArrayList<>(); private final Collection mainSourceFiles_ = new ArrayList<>(); private final Collection plugins_ = new ArrayList<>(); @@ -53,188 +49,52 @@ public class CompileKotlinOperation extends AbstractOperation testSourceFiles_ = new ArrayList<>(); private File buildMainDirectory_; private File buildTestDirectory_; - private CompileOptions compileOptions_ = new CompileOptions(); - private File kotlinHome_; - private File kotlinc_; + private CompileKotlinOptions compileOptions_ = new CompileKotlinOptions(); private BaseProject project_; - private File workDir_; - - private static String findKotlincInDir(String directory) { - var kotlinc = new File(directory, KOTLINC_EXECUTABLE); - - if (isExecutable(kotlinc)) { - return kotlinc.getAbsolutePath(); - } - - // Check bin subdirectory if it exists - var binDir = new File(directory, "bin"); - if (binDir.isDirectory()) { - kotlinc = new File(binDir, KOTLINC_EXECUTABLE); - if (isExecutable(kotlinc)) { - return kotlinc.getAbsolutePath(); - } - } - - return null; - } /** - * Locates the Kotlin compiler (kotlinc) executable. + * Returns the list of JARs contained in a given directory. * - * @return The path to the kotlinc executable, or {@code kotlinc}/{@code kotlinc.bat} if not found. - * @since 1.1.0 + * @param directory the directory + * @param regex the regular expression to match + * @return the list of JARs */ - public static String findKotlincPath() { - return findKotlincPath(false); - } + public static List getJarList(File directory, String regex) { + var jars = new ArrayList(); - /** - * Locates the Kotlin compiler (kotlinc) executable. - * - * @param isSilent do not log the path to the kotlinc executable, if {@code true} - * @return The path to the kotlinc executable, or {@code kotlinc}/{@code kotlinc.bat} if not found. - * @since 1.1.0 - */ - public static String findKotlincPath(boolean isSilent) { - String kotlincPath; - - // Check KOTLIN_HOME environment variable first - var kotlinHome = System.getenv("KOTLIN_HOME"); - if (kotlinHome != null && !kotlinHome.isEmpty()) { - kotlincPath = findKotlincInDir(kotlinHome); - if (kotlincPath != null) { - logKotlincPath(kotlincPath, isSilent, "KOTLIN_HOME"); - return kotlincPath; - } - } - - // Check PATH environment variable - var pathEnv = System.getenv("PATH"); - if (pathEnv != null && !pathEnv.isEmpty()) { - var pathDirs = pathEnv.split(File.pathSeparator); - for (var dir : pathDirs) { - kotlincPath = findKotlincInDir(dir); - if (kotlincPath != null) { - logKotlincPath(kotlincPath, isSilent, "PATH"); - return kotlincPath; - } - } - } - - // Common installation paths (e.g., SDKMAN!, IntelliJ IDEA, etc.) - var commonPaths = new LinkedHashMap(); - - if (isLinux()) { - var userHome = System.getProperty("user.home"); - if (userHome != null) { - commonPaths.put(userHome + "/.sdkman/candidates/kotlin/current/bin", "SDKMAN!"); - } - commonPaths.put("/snap/bin", "Kotlin (Snap)"); - commonPaths.put("/usr/bin", null); - commonPaths.put("/usr/share", null); - commonPaths.put("/usr/local/bin", null); - commonPaths.put("/usr/local/kotlin/bin", null); - commonPaths.put("/usr/share/kotlin/bin/", null); - commonPaths.put("/opt/kotlin/bin", null); - if (userHome != null) { - commonPaths.put(userHome + "/.local/share/JetBrains/Toolbox/apps/intellij-idea-ultimate/plugins/Kotlin/kotlinc/bin", - "IntelliJ IDEA Ultimate"); - commonPaths.put(userHome + "/.local/share/JetBrains/Toolbox/apps/intellij-idea-community-edition/plugins/Kotlin/kotlinc/bin", - "IntelliJ IDEA Community Edition"); - commonPaths.put(userHome + "/.local/share/JetBrains/Toolbox/apps/android-studio/plugins/Kotlin/kotlinc/bin", - "Android Studio"); - } - commonPaths.put("/snap/intellij-idea-ultimate/current/commons/plugins/Kotlin/kotlinc/bin", - "IntelliJ IDEA Ultimate (Snap)"); - commonPaths.put("/snap/intellij-idea-community/current/commons/plugins/Kotlin/kotlinc/bin", - "IntelliJ IDEA Community Edition (Snap)"); - commonPaths.put("/snap/android-studio/current/android-studio/commons/plugins/Kotlin/kotlinc/bin", - "Android Studio (Snap)"); - } else if (isWindows()) { - commonPaths.put("C:\\tools\\kotlinc\\bin", null); - var localAppData = System.getenv("LOCALAPPDATA"); - if (localAppData != null) { - commonPaths.put(localAppData + "\\Programs\\IntelliJ IDEA Ultimate\\plugins\\Kotlin\\kotlinc\\bin", - "IntelliJ IDEA Ultimate"); - commonPaths.put(localAppData + "\\Programs\\IntelliJ IDEA Community Edition\\plugins\\Kotlin\\kotlinc\\bin", - "IntelliJ IDEA Community Edition"); - commonPaths.put(localAppData + "\\Programs\\Android Studio\\plugins\\Kotlin\\kotlinc\\bin", - "Android Studio"); - } - var programFiles = System.getenv("ProgramFiles"); - if (programFiles != null) { - commonPaths.put(programFiles + "\\Kotlin\\bin", null); - } - } else if (isMacOS()) { - var userHome = System.getProperty("user.home"); - if (userHome != null) { - commonPaths.put(userHome + "/.sdkman/candidates/kotlin/current/bin", "SDKMAN!"); - } - commonPaths.put("/opt/homebrew/bin", "Homebrew"); - commonPaths.put("/usr/local/bin", null); - commonPaths.put("/Applications/IntelliJ IDEA.app/Contents/plugins/Kotlin/kotlinc/bin/", - "IntelliJ IDEA"); - commonPaths.put("/Applications/IntelliJ IDEA Community Edition.app/Contents/plugins/Kotlin/kotlinc/bin/", - "IntelliJ IDEA Community Edition"); - commonPaths.put("/Applications/Android Studio.app/Contents/plugins/Kotlin/kotlinc/bin", - "Android Studio"); - } - - for (var path : commonPaths.keySet()) { - kotlincPath = findKotlincInDir(path); - if (kotlincPath != null) { - logKotlincPath(kotlincPath, isSilent, commonPaths.get(path)); - return kotlincPath; - } - } - - // Try 'which' or 'where' commands (less reliable but sometimes works) - try { - Process process; - if (isWindows()) { - process = Runtime.getRuntime().exec("where kotlinc"); - } else { - process = Runtime.getRuntime().exec("which kotlinc"); - } - - try (var scanner = new Scanner(process.getInputStream())) { - if (scanner.hasNextLine()) { - kotlincPath = scanner.nextLine().trim(); - if (isExecutable(new File(kotlincPath))) { - logKotlincPath(kotlincPath, isSilent); - return kotlincPath; + if (directory.isDirectory()) { + var files = directory.listFiles(); + if (files != null) { + for (var f : files) { + if (!f.getName().endsWith("-sources.jar") && (!f.getName().endsWith("-javadoc.jar")) && + f.getName().matches(regex)) { + jars.add(f.getAbsolutePath()); } } } - } catch (Exception ignored) { - // Ignore exceptions from which/where, as they might not be available } - return KOTLINC_EXECUTABLE; - } - - private static boolean isExecutable(File file) { - return file != null && file.exists() && file.isFile() && file.canExecute(); + return jars; } /** - * Determines if the operating system is Linux. + * Returns the list of Kotlin source file {{@code .kt}} contained in a given directory. * - * @return true if the operating system is Linux, false otherwise. - * @since 1.1.0 + * @param directory the directory + * @return the list of Kotlin files */ - public static boolean isLinux() { - return OS_NAME != null && (OS_NAME.contains("linux") || OS_NAME.contains("unix")); // Consider Unix-like systems as well. - } - - /** - * Determines if the current operating system is macOS. - * - * @return true if the OS is macOS, false otherwise. - * @since 1.1.0 - */ - public static boolean isMacOS() { - return OS_NAME != null && (OS_NAME.contains("mac") || OS_NAME.contains("darwin") || OS_NAME.contains("osx")); + public static Collection getKotlinFileList(File directory) { + if (directory == null) { + return Collections.emptyList(); + } else if (!directory.exists()) { + if (LOGGER.isLoggable(Level.WARNING)) { + LOGGER.warning("Directory not found: " + directory.getAbsolutePath()); + } + return Collections.emptyList(); + } else { + return FileUtils.getFileList(directory, KOTLIN_FILE_PATTERN, null).stream().map((file) -> + new File(directory, file)).toList(); + } } /** @@ -247,40 +107,6 @@ public class CompileKotlinOperation extends AbstractOperation classpath) { @@ -385,30 +170,30 @@ public class CompileKotlinOperation extends AbstractOperation compileMainClasspath() { return compileMainClasspath_; } /** - * Retrieves the compilation options for the compiler. + * Retrieves the list of compilation options for the compiler. * - * @return the compilation options + * @return the compile kotlin options */ - public CompileOptions compileOptions() { + public CompileKotlinOptions compileOptions() { return compileOptions_; } /** - * Provides the compilation options to pass to the Kotlin compiler. + * Provides a list of compilation options to pass to the Kotlin compiler. * * @param options the compiler options * @return this operation instance */ - public CompileKotlinOperation compileOptions(CompileOptions options) { + public CompileKotlinOperation compileOptions(CompileKotlinOptions options) { compileOptions_ = options; return this; } @@ -420,13 +205,14 @@ public class CompileKotlinOperation extends AbstractOperation classpath) { @@ -435,9 +221,9 @@ public class CompileKotlinOperation extends AbstractOperation compileTestClasspath() { return compileTestClasspath_; @@ -448,17 +234,10 @@ public class CompileKotlinOperation extends AbstractOperation classpath, Collection sources, File destination, File friendPaths) - throws ExitStatusException { - - var cp = new ArrayList(); - if (classpath != null && !classpath.isEmpty()) { - cp.addAll(classpath); - } - - if (sources.isEmpty()) { - if (!silent() && LOGGER.isLoggable(Level.WARNING)) { - LOGGER.warning("Nothing to compile."); - } + throws IOException { + if (sources.isEmpty() || destination == null) { return; - } else if (destination == null) { - if (!silent() && LOGGER.isLoggable(Level.SEVERE)) { - LOGGER.severe("No destination specified."); - } - throw new ExitStatusException(ExitStatusException.EXIT_FAILURE); } - var command = new ArrayList(); + var k2 = new K2JVMCompiler(); var args = new ArrayList(); - // kotlinc - if (kotlinc_ != null) { - command.add(kotlinc_.getAbsolutePath()); - } else if (kotlinHome_ != null) { - var kotlinc = findKotlincInDir(kotlinHome_.getAbsolutePath()); - if (kotlinc != null) { - command.add(kotlinc); - } else { - if (LOGGER.isLoggable(Level.SEVERE) && !silent()) { - LOGGER.severe("Could not locate Kotlin compiler in: " + kotlinHome_); - } - throw new ExitStatusException(ExitStatusException.EXIT_FAILURE); - } - } else { - command.add(findKotlincPath(silent())); - } - - // JVM options - if (!jvmOptions_.isEmpty()) { - jvmOptions_.forEach(s -> command.add("-J" + s)); - } - // classpath - if (compileOptions_ != null && !compileOptions_.classpath().isEmpty()) { - cp.addAll(compileOptions_.classpath().stream().map(this::cleanPath).toList()); - } - if (!cp.isEmpty()) { - args.add("-cp"); - args.add('"' + FileUtils.joinPaths(cp.stream().map(this::cleanPath).toList()) + '"'); - } - - // compile options - if (compileOptions_ != null && !compileOptions_.args().isEmpty()) { - args.addAll(compileOptions_.args()); - } + args.add("-cp"); + args.add(FileUtils.joinPaths(classpath.stream().toList())); // destination args.add("-d"); - args.add('"' + cleanPath(destination) + '"'); + args.add(destination.getAbsolutePath()); // friend-path if (friendPaths != null && friendPaths.exists()) { - args.add("-Xfriend-paths=\"" + cleanPath(friendPaths) + '"'); + args.add("-Xfriend-paths=" + friendPaths.getAbsolutePath()); + } + + // options + if (compileOptions_ != null) { + args.addAll(compileOptions_.args()); } // plugins if (!plugins_.isEmpty()) { - plugins_.forEach(p -> args.add("-Xplugin=\"" + cleanPath(p) + '"')); + plugins_.forEach(p -> args.add("-Xplugin=" + p)); } // sources - sources.forEach(f -> args.add('"' + cleanPath(f) + '"')); + sources.forEach(f -> args.add(f.getAbsolutePath())); - var argsLine = String.join(" ", args); - - // log the command line if (LOGGER.isLoggable(Level.FINE) && !silent()) { - LOGGER.fine(String.join(" ", command) + " " + argsLine); + LOGGER.fine("kotlinc " + String.join(" ", args)); } - try { - // create and write the @argfile - var argsFile = File.createTempFile("bld-kotlinc-", ".args"); - argsFile.deleteOnExit(); - - Files.write(argsFile.toPath(), argsLine.getBytes()); - - command.add("@" + argsFile.getAbsolutePath()); - - // run the command - var pb = new ProcessBuilder(); - pb.inheritIO(); - pb.command(command); - pb.directory(workDir_); - - var proc = pb.start(); - proc.waitFor(); - ExitStatusException.throwOnFailure(proc.exitValue()); - } catch (IOException | InterruptedException e) { - if (LOGGER.isLoggable(Level.SEVERE) && !silent()) { - LOGGER.severe(e.getLocalizedMessage()); - } - throw new ExitStatusException(ExitStatusException.EXIT_FAILURE); + var exitCode = k2.exec(System.err, args.toArray(new String[0])); + if (exitCode.getCode() != 0) { + throw new IOException("Kotlin compilation failed."); } } /** * Part of the {@link #execute execute} operation, builds the test sources. * - * @throws ExitStatusException if an error occurs + * @throws IOException if an error occurs */ @SuppressWarnings("PMD.SystemPrintln") - protected void executeBuildTestSources() throws ExitStatusException { + protected void executeBuildTestSources() + throws IOException { if (!silent()) { System.out.println("Compiling Kotlin test sources."); } @@ -632,52 +348,28 @@ public class CompileKotlinOperation extends AbstractOperation * Sets the following from the project: *
    - *
  • {@link #workDir() workDir} to the project's directory.
  • *
  • {@link #buildMainDirectory() buildMainDirectory}
  • *
  • {@link #buildTestDirectory() buildTestDirectory}
  • *
  • {@link #compileMainClasspath() compileMainClassPath}
  • *
  • {@link #compileTestClasspath() compilesTestClassPath}
  • - *
  • {@link #mainSourceDirectories() mainSourceDirectories} to the {@code kotlin} directory in - * {@link BaseProject#srcMainDirectory() srcMainDirectory}, if present.
  • - *
  • {@link #testSourceDirectories() testSourceDirectories} to the {@code kotlin} directory in - * {@link BaseProject#srcTestDirectory() srcTestDirectory}, if present.
  • - *
  • {@link CompileOptions#jdkRelease jdkRelease} to {@link BaseProject#javaRelease() javaRelease}
  • - *
  • {@link CompileOptions#noStdLib(boolean) noStdLib} to {@code true}
  • + *
  • {@link #mainSourceFiles() mainSourceFiles} to the {@code kotlin} directory in + * {@link BaseProject#srcMainDirectory() srcMainDirectory}
  • + *
  • {@link #testSourceFiles() testSourceFile} to the {@code kotlin} directory in + * {@link BaseProject#srcTestDirectory() srcTestDirectory}
  • + *
  • {@link CompileKotlinOptions#jdkRelease jdkRelease} to {@link BaseProject#javaRelease() javaRelease}
  • + *
  • {@link CompileKotlinOptions#noStdLib(boolean) noStdLib} to {@code true}
  • *
* * @param project the project to configure the compile operation from @@ -685,22 +377,12 @@ public class CompileKotlinOperation extends AbstractOperation jvmOptions) { - jvmOptions_.addAll(jvmOptions); - return this; - } - - /** - * Pass an option directly to the Java Virtual Machine - * - * @param jvmOptions one or more JVM option - * @return this operation instance - */ - public CompileKotlinOperation jvmOptions(String... jvmOptions) { - return jvmOptions(List.of(jvmOptions)); - } - - /** - * Provides the Kotlin home directory, if it differs from the default {@code KOTLIN_HOME}. - * - * @param dir the directory - * @return this operation instance - */ - public CompileKotlinOperation kotlinHome(File dir) { - kotlinHome_ = dir; - return this; - } - - /** - * Provides the Kotlin home directory, if it differs from the default {@code KOTLIN_HOME}. - * - * @param dir the directory path - * @return this operation instance - */ - public CompileKotlinOperation kotlinHome(String dir) { - return kotlinHome(new File(dir)); - } - - /** - * Provides the Kotlin home directory, if it differs from the default {@code KOTLIN_HOME}. - * - * @param dir the directory path - * @return this operation instance - */ - public CompileKotlinOperation kotlinHome(Path dir) { - return kotlinHome(dir.toFile()); - } - - /** - * Retrieves the Kotlin home directory. - * - * @return the directory - */ - public File kotlinHome() { - return kotlinHome_; - } - - /** - * Retrieves the path to the Kotlin compiler ({@code kotlinc}) executable, if not in {@link #kotlinHome()}. - * - * @return the executable path - */ - public File kotlinc() { - return kotlinc_; - } - - /** - * Provides the path to the Kotlin compiler ({@code kotlinc}) executable, if not in {@link #kotlinHome()}. - * - * @param executable the executable path - * @return this operation instance - */ - public CompileKotlinOperation kotlinc(File executable) { - kotlinc_ = executable; - return this; - } - - /** - * Provides the path to the Kotlin compiler ({@code kotlinc}) executable, if not in {@link #kotlinHome()}. - * - * @param executable the executable path - * @return this operation instance - */ - public CompileKotlinOperation kotlinc(String executable) { - return kotlinc(new File(executable)); - } - - /** - * Provides the path to the Kotlin compiler ({@code kotlinc}) executable, if not in {@link #kotlinHome()}. - * - * @param executable the executable path - * @return this operation instance - */ - public CompileKotlinOperation kotlinc(Path executable) { - return kotlinc(executable.toFile()); - } - /** * Provides main source directories that should be compiled. * * @param directories one or more main source directories * @return this operation instance - * @see #mainSourceDirectories(Collection) */ public CompileKotlinOperation mainSourceDirectories(File... directories) { - return mainSourceDirectories(List.of(directories)); + mainSourceDirectories_.addAll(List.of(directories)); + return this; } /** - * Provides main source directories that should be compiled. + * Provides a list of main source directories that should be compiled. * - * @param directories one or more main source directories + * @param directories a list of main source directories * @return this operation instance - * @see #mainSourceDirectoriesPaths(Collection) - */ - public CompileKotlinOperation mainSourceDirectories(Path... directories) { - return mainSourceDirectoriesPaths(List.of(directories)); - } - - /** - * Provides main source directories that should be compiled. - * - * @param directories one or more main source directories - * @return this operation instance - * @see #mainSourceDirectoriesStrings(Collection) - */ - public CompileKotlinOperation mainSourceDirectories(String... directories) { - return mainSourceDirectoriesStrings(List.of(directories)); - } - - /** - * Provides the main source directories that should be compiled. - * - * @param directories the main source directories - * @return this operation instance - * @see #mainSourceDirectories(File...) */ public CompileKotlinOperation mainSourceDirectories(Collection directories) { mainSourceDirectories_.addAll(directories); @@ -865,75 +414,30 @@ public class CompileKotlinOperation extends AbstractOperation mainSourceDirectories() { return mainSourceDirectories_; } /** - * Provides the main source directories that should be compiled. + * Provides main files that should be compiled. * - * @param directories the main source directories + * @param files one or more main files * @return this operation instance - * @see #mainSourceDirectories(Path...) - */ - public CompileKotlinOperation mainSourceDirectoriesPaths(Collection directories) { - return mainSourceDirectories(directories.stream().map(Path::toFile).toList()); - } - - /** - * Provides the main source directories that should be compiled. - * - * @param directories the main source directories - * @return this operation instance - * @see #mainSourceDirectories(String...) - */ - public CompileKotlinOperation mainSourceDirectoriesStrings(Collection directories) { - return mainSourceDirectories(directories.stream().map(File::new).toList()); - } - - /** - * Provides main source files that should be compiled. - * - * @param files one or more main source files - * @return this operation instance - * @see #mainSourceFiles(Collection) */ public CompileKotlinOperation mainSourceFiles(File... files) { - return mainSourceFiles(List.of(files)); + mainSourceFiles_.addAll(Arrays.asList(files)); + return this; } /** - * Provides main source files that should be compiled. + * Provides a list of main files that should be compiled. * - * @param files one or more main source files + * @param files a list of main files * @return this operation instance - * @see #mainSourceFilesStrings(Collection) - */ - public CompileKotlinOperation mainSourceFiles(String... files) { - return mainSourceFilesStrings(List.of(files)); - } - - /** - * Provides main source files that should be compiled. - * - * @param files one or more main source files - * @return this operation instance - * @see #mainSourceFilesPaths(Collection) - */ - public CompileKotlinOperation mainSourceFiles(Path... files) { - return mainSourceFilesPaths(List.of(files)); - } - - /** - * Provides the main source files that should be compiled. - * - * @param files the main source files - * @return this operation instance - * @see #mainSourceFiles(File...) */ public CompileKotlinOperation mainSourceFiles(Collection files) { mainSourceFiles_.addAll(files); @@ -941,47 +445,14 @@ public class CompileKotlinOperation extends AbstractOperation mainSourceFiles() { return mainSourceFiles_; } - /** - * Provides the main source files that should be compiled. - * - * @param files the main source files - * @return this operation instance - * @see #mainSourceFiles(Path...) - */ - public CompileKotlinOperation mainSourceFilesPaths(Collection files) { - return mainSourceFiles(files.stream().map(Path::toFile).toList()); - } - - /** - * Provides the main source files that should be compiled. - * - * @param files the main source files - * @return this operation instance - * @see #mainSourceFiles(String...) - */ - public CompileKotlinOperation mainSourceFilesStrings(Collection files) { - return mainSourceFiles(files.stream().map(File::new).toList()); - } - - /** - * Provides compiler plugins. - * - * @param directory the directory containing the plugin JARs - * @param plugins one or more plugins - * @return this class instance - */ - public CompileKotlinOperation plugins(String directory, CompilerPlugin... plugins) { - return plugins(new File(directory), plugins); - } - /** * Provides compiler plugins. * @@ -989,22 +460,14 @@ public class CompileKotlinOperation extends AbstractOperation plugins() { - return plugins_; + plugins_.addAll(List.of(plugins)); + return this; } /** * Provides compiler plugins. * - * @param plugins the compiler plugins + * @param plugins a list of plugins * @return this class instance */ public CompileKotlinOperation plugins(Collection plugins) { @@ -1019,9 +482,9 @@ public class CompileKotlinOperation extends AbstractOperation jars, CompileKotlinPlugin... plugins) { + jars.forEach(jar -> { for (var plugin : plugins) { - plugins(kotlinLib, plugin); + if (jar.getName().matches(plugin.label)) { + plugins_.add(jar.getAbsolutePath()); + break; + } } - } else if (LOGGER.isLoggable(Level.WARNING) && !silent()) { - LOGGER.warning("The Kotlin home must be set (or discovered) to specify compiler plugins directly."); - } + }); + return this; } // Combine Kotlin sources private Collection sources(Collection files, Collection directories) { var sources = new ArrayList<>(files); - sources.addAll(directories); + for (var directory : directories) { + sources.addAll(getKotlinFileList(directory)); + } + return sources; } @@ -1072,40 +524,17 @@ public class CompileKotlinOperation extends AbstractOperation directories) { testSourceDirectories_.addAll(directories); @@ -1113,75 +542,30 @@ public class CompileKotlinOperation extends AbstractOperation testSourceDirectories() { return testSourceDirectories_; } /** - * Provides the test source directories that should be compiled. + * Provides test files that should be compiled. * - * @param directories the test source directories + * @param files one or more test files * @return this operation instance - * @see #testSourceDirectories(Path...) - */ - public CompileKotlinOperation testSourceDirectoriesPaths(Collection directories) { - return testSourceDirectories(directories.stream().map(Path::toFile).toList()); - } - - /** - * Provides the test source directories that should be compiled. - * - * @param directories the test source directories - * @return this operation instance - * @see #testSourceDirectories(String...) - */ - public CompileKotlinOperation testSourceDirectoriesStrings(Collection directories) { - return testSourceDirectories(directories.stream().map(File::new).toList()); - } - - /** - * Provides test source files that should be compiled. - * - * @param files one or more test source files - * @return this operation instance - * @see #testSourceFiles(Collection) */ public CompileKotlinOperation testSourceFiles(File... files) { - return testSourceFiles(List.of(files)); + testSourceFiles_.addAll(Arrays.asList(files)); + return this; } /** - * Provides the test sources files that should be compiled. + * Provides a list of test files that should be compiled. * - * @param files one or more test source files + * @param files a list of test files * @return this operation instance - * @see #testSourceFilesStrings(Collection) - */ - public CompileKotlinOperation testSourceFiles(String... files) { - return testSourceFilesStrings(List.of(files)); - } - - /** - * Provides the test sources files that should be compiled. - * - * @param files one or more test source files - * @return this operation instance - * @see #testSourceFilesPaths(Collection) - */ - public CompileKotlinOperation testSourceFiles(Path... files) { - return testSourceFilesPaths(List.of(files)); - } - - /** - * Provides the test source files that should be compiled. - * - * @param files the test source files - * @return this operation instance - * @see #testSourceFiles(File...) */ public CompileKotlinOperation testSourceFiles(Collection files) { testSourceFiles_.addAll(files); @@ -1189,73 +573,11 @@ public class CompileKotlinOperation extends AbstractOperation testSourceFiles() { return testSourceFiles_; } - - /** - * Provides the test source files that should be compiled. - * - * @param files the test source files - * @return this operation instance - * @see #testSourceFiles(Path...) - */ - public CompileKotlinOperation testSourceFilesPaths(Collection files) { - return testSourceFiles(files.stream().map(Path::toFile).toList()); - } - - /** - * Provides the test source files that should be compiled. - * - * @param files the test source files - * @return this operation instance - * @see #testSourceFiles(String...) - */ - public CompileKotlinOperation testSourceFilesStrings(Collection files) { - return testSourceFiles(files.stream().map(File::new).toList()); - } - - /** - * Retrieves the working directory. - * - * @return the directory - */ - public File workDir() { - return workDir_; - } - - /** - * Provides the working directory, if it differs from the project's directory. - * - * @param dir the directory - * @return this operation instance - */ - public CompileKotlinOperation workDir(File dir) { - workDir_ = dir; - return this; - } - - /** - * Provides the working directory, if it differs from the project's directory. - * - * @param dir the directory - * @return this operation instance - */ - public CompileKotlinOperation workDir(Path dir) { - return workDir(dir.toFile()); - } - - /** - * Provides the working directory, if it differs from the project's directory. - * - * @param dir the directory path - * @return this operation instance - */ - public CompileKotlinOperation workDir(String dir) { - return workDir(new File(dir)); - } } diff --git a/src/main/java/rife/bld/extension/CompileKotlinOptions.java b/src/main/java/rife/bld/extension/CompileKotlinOptions.java new file mode 100644 index 0000000..343d1ba --- /dev/null +++ b/src/main/java/rife/bld/extension/CompileKotlinOptions.java @@ -0,0 +1,581 @@ +/* + * Copyright 2023-2024 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 java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import static rife.bld.extension.CompileKotlinOperation.isNotBlank; + +/** + * Configuration for the Kotlin compiler options. + * + * @author Erik C. Thauvin + * @since 1.0 + */ +public class CompileKotlinOptions { + private final List argFile_ = new ArrayList<>(); + private final List classpath_ = new ArrayList<>(); + private final List optIn_ = new ArrayList<>(); + private final List options_ = new ArrayList<>(); + private final List plugin_ = new ArrayList<>(); + private final List scriptTemplates_ = new ArrayList<>(); + private String apiVersion_; + private boolean includeRuntime_; + private boolean javaParameters_; + private String jdkHome_; + private String jdkRelease_; + private String jvmTarget_; + private String kotlinHome_; + private String languageVersion_; + private String moduleName_; + private boolean noJdk_; + private boolean noReflect_; + private boolean noStdLib_; + private boolean noWarn_; + private String path_; + private boolean progressive_; + private boolean verbose_; + private boolean wError_; + + /** + * Allow using declarations only from the specified version of Kotlin bundled libraries. + * + * @param version the api version + * @return this operation instance + */ + public CompileKotlinOptions apiVersion(String version) { + apiVersion_ = version; + return this; + } + + /** + * Read the compiler options from the given files. + *

+ * Such a file can contain compiler options with values and paths to the source files. + * Options and paths should be separated by whitespaces. For example: + *

    + *
  • {@code -include-runtime -d hello.jar hello.kt}
  • + *
+ * To pass values that contain whitespaces, surround them with single ({@code '}) or double ({@code "}) quotes. + * If a value contains quotation marks in it, escape them with a backslash (\). + *
    + *
  • {@code -include-runtime -d 'My folder'}
  • + *
+ * If the files reside in locations different from the current directory, use relative paths. + * + * @param files one or more files + * @return this operation instance + */ + public CompileKotlinOptions argFile(String... files) { + argFile_.addAll(List.of(files)); + return this; + } + + /** + * Read the compiler options from the given files. + * + * @param files the list of files + * @return this operation instance + * @see #argFile(String...) + */ + public CompileKotlinOptions argFile(Collection files) { + argFile_.addAll(files); + return this; + } + + /** + * Returns the formatted arguments. + * + * @return the arguments + */ + public List args() { + var args = new ArrayList(); + + // api-isNotBlankversion + if (isNotBlank(apiVersion_)) { + args.add("-api-version"); + args.add(apiVersion_); + } + + // @argfile + if (!argFile_.isEmpty()) { + argFile_.forEach(f -> args.add("@" + f)); + } + + // classpath + if (!classpath_.isEmpty()) { + args.add("-classpath"); + args.add(String.join(File.pathSeparator, classpath_)); + } + + // java-parameters + if (javaParameters_) { + args.add("-java-parameters"); + } + + // jvm-target + if (isNotBlank(jvmTarget_)) { + args.add("-jvm-target"); + args.add(jvmTarget_); + } + + // include-runtime + if (includeRuntime_) { + args.add("-include-runtime"); + } + + // jdk-home + if (isNotBlank(jdkHome_)) { + args.add("-jdk-home"); + args.add(jdkHome_); + } + + // jdk-release + if (isNotBlank(jdkRelease_)) { + args.add("-Xjdk-release=" + jdkRelease_); + } + + // kotlin-home + if (isNotBlank(kotlinHome_)) { + args.add("-kotlin-home"); + args.add(kotlinHome_); + } + + // language-version + if (isNotBlank(languageVersion_)) { + args.add("-language-version"); + args.add(languageVersion_); + } + + // module-name + if (isNotBlank(moduleName_)) { + args.add("-module-name"); + args.add(moduleName_); + } + + // no-jdk + if (noJdk_) { + args.add("-no-jdk"); + } + + // no-reflect + if (noReflect_) { + args.add("-no-reflect"); + } + + // no-std-lib + if (noStdLib_) { + args.add("-no-stdlib"); + } + + // no-warn + if (noWarn_) { + args.add("-no-warn"); + } + + // opt-in + optIn_.stream().filter(CompileKotlinOperation::isNotBlank).forEach(o -> { + args.add("-opt-in"); + args.add(o); + }); + + // options + if (!options_.isEmpty()) { + args.addAll(options_); + } + + // path + if (isNotBlank(path_)) { + args.add("-d"); + args.add(path_); + } + + // plugin + plugin_.stream().filter(CompileKotlinOperation::isNotBlank).forEach(p -> { + args.add("-P"); + args.add("plugin:" + p); + }); + + // progressive + if (progressive_) { + args.add("-progressive"); + } + + // script-templates + if (!scriptTemplates_.isEmpty()) { + args.add("-script-templates"); + args.add(String.join(",", scriptTemplates_)); + } + + // verbose + if (verbose_) { + args.add("-verbose"); + } + + // Werror + if (wError_) { + args.add("-Werror"); + } + + return args; + } + + /** + * Search for class files in the specified paths. + *

+ * The classpath can contain file and directory paths, ZIP, or JAR files. + * + * @param paths one pr more paths + * @return this operation instance + */ + public CompileKotlinOptions classpath(String... paths) { + classpath_.addAll(List.of(paths)); + return this; + } + + /** + * Search for class files in the specified paths. + *

+ * The classpath can contain file and directory paths, ZIP, or JAR files. + * + * @param paths the list of paths + * @return this operation instance + */ + public CompileKotlinOptions classpath(Collection paths) { + classpath_.addAll(paths); + return this; + } + + /** + * Indicates whether the {@link #jdkRelease(String) jdkRelease} was set. + * + * @return {@code true} if the release was set; or {@code false} otherwise + */ + public boolean hasRelease() { + return jdkRelease_ != null; + } + + /** + * Include the Kotlin runtime into the resulting JAR file. Makes the resulting archive runnable on any Java-enabled + * environment. + * + * @param includeRuntime {@code true} or {@code false} + * @return this operation instance + */ + public CompileKotlinOptions includeRuntime(boolean includeRuntime) { + includeRuntime_ = includeRuntime; + return this; + } + + /** + * Generate metadata for Java 1.8 reflection on method parameters. + * + * @param javaParameters {@code true} or {@code false} + * @return this operation instance + */ + public CompileKotlinOptions javaParameters(boolean javaParameters) { + javaParameters_ = javaParameters; + return this; + } + + /** + * Use a custom JDK home directory to include into the classpath if it differs from the default {@code JAVA_HOME}. + * + * @param jdkHome the JDK home path + * @return this operation instance + */ + public CompileKotlinOptions jdkHome(String jdkHome) { + jdkHome_ = jdkHome; + return this; + } + + /** + * Specify the target version of the generated JVM bytecode. + *

+ * Limit the API of the JDK in the classpath to the specified Java version. Automatically sets + * {@link #jvmTarget(String) JVM target} version. + *

+ * Possible values are 1.8, 9, 10, ..., 21. The default value is 1.8. + * + * @param version the target version + * @return this operation instance + */ + public CompileKotlinOptions jdkRelease(String version) { + jdkRelease_ = version; + return this; + } + + /** + * Specify the target version of the generated JVM bytecode. + * + * @param version the target version + * @return this operation instance + * @see #jdkRelease(String) + */ + public CompileKotlinOptions jdkRelease(int version) { + jdkRelease_ = String.valueOf(version); + return this; + } + + /** + * Specify the target version of the generated JVM bytecode. + *

+ * Possible values are 1.8, 9, 10, ..., 21. The default value is 1.8. + * + * @param target the target version + * @return this operation instance + */ + public CompileKotlinOptions jvmTarget(String target) { + jvmTarget_ = target; + return this; + } + + /** + * Specify the target version of the generated JVM bytecode. + * + * @param target the target version + * @return this operation instance + * @see #jvmTarget(String) + */ + public CompileKotlinOptions jvmTarget(int target) { + jvmTarget_ = String.valueOf(target); + return this; + } + + /** + * Specify a custom path to the Kotlin compiler used for the discovery of runtime libraries. + * + * @param path the Kotlin home path + * @return this operation instance + */ + public CompileKotlinOptions kotlinHome(String path) { + kotlinHome_ = path; + return this; + } + + /** + * Provide source compatibility with the specified version of Kotlin. + * + * @param version the language version + * @return this operation instance + */ + public CompileKotlinOptions languageVersion(String version) { + languageVersion_ = version; + return this; + } + + /** + * Set a custom name for the generated {@code .kotlin_module} file. + * + * @param name the module name + * @return this operation instance + */ + public CompileKotlinOptions moduleName(String name) { + moduleName_ = name; + return this; + } + + /** + * Don't automatically include the Java runtime into the classpath. + * + * @param noJdk {@code true} or {@code false} + * @return this operation instance + */ + public CompileKotlinOptions noJdk(boolean noJdk) { + noJdk_ = noJdk; + return this; + } + + /** + * Don't automatically include the Kotlin reflection ({@code kotlin-reflect.jar}) into the classpath. + * + * @param noReflect {@code true} or {@code false} + * @return this operation instance + */ + public CompileKotlinOptions noReflect(boolean noReflect) { + noReflect_ = noReflect; + return this; + } + + /** + * Don't automatically include the Kotlin/JVM stdlib ({@code kotlin-stdlib.jar}) and Kotlin reflection + * ({@code kotlin-reflect.jar}) into the classpath. + * + * @param noStdLib {@code true} or {@code false} + * @return this operation instance + */ + public CompileKotlinOptions noStdLib(boolean noStdLib) { + noStdLib_ = noStdLib; + return this; + } + + /** + * Suppress the compiler from displaying warnings during compilation. + * + * @param noWarn {@code true} or {@code false} + * @return this operation instance + */ + public CompileKotlinOptions noWarn(boolean noWarn) { + noWarn_ = noWarn; + return this; + } + + /** + * Enable usages of API that requires opt-in with a requirement annotation with the given fully qualified name. + * + * @param annotations one or more annotation names + * @return this operation instance + */ + public CompileKotlinOptions optIn(String... annotations) { + optIn_.addAll(List.of(annotations)); + return this; + } + + /** + * Enable usages of API that requires opt-in with a requirement annotation with the given fully qualified name. + * + * @param annotations list of annotation names + * @return this operation instance + */ + public CompileKotlinOptions optIn(Collection annotations) { + optIn_.addAll(annotations); + return this; + } + + /** + * Specify additional compiler options. + * + * @param options one or more compiler options + * @return this operation instance + */ + public CompileKotlinOptions options(String... options) { + options_.addAll(List.of(options)); + return this; + } + + /** + * Specify additional compiler options. + * + * @param options list of compiler options + * @return this operation instance + */ + public CompileKotlinOptions options(Collection options) { + options_.addAll(options); + return this; + } + + /** + * Place the generated class files into the specified location. + *

+ * The location can be a directory, a ZIP, or a JAR file. + * + * @param path the location path + * @return this operation instance + */ + public CompileKotlinOptions path(File path) { + path_ = path.getAbsolutePath(); + return this; + } + + /** + * Place the generated class files into the specified location. + *

+ * The location can be a directory, a ZIP, or a JAR file. + * + * @param path the location path + * @return this operation instance + */ + public CompileKotlinOptions path(String path) { + path_ = path; + return this; + } + + /** + * Pass an option to a plugin. + * + * @param id the plugin ID + * @param optionName the plugin option name + * @param value the plugin option value + * @return this operation instance + */ + public CompileKotlinOptions plugin(String id, String optionName, String value) { + plugin_.add(id + ':' + optionName + ':' + value); + return this; + } + + /** + * Allow using declarations only from the specified version of Kotlin bundled libraries. + * + * @param progressive {@code true} or {@code false} + * @return this operation instance + */ + public CompileKotlinOptions progressive(boolean progressive) { + progressive_ = progressive; + return this; + } + + /** + * Script definition template classes. + *

+ * Use fully qualified class names. + * + * @param classNames one or more class names + * @return this operation instance + */ + public CompileKotlinOptions scriptTemplates(String... classNames) { + scriptTemplates_.addAll(List.of(classNames)); + return this; + } + + /** + * Script definition template classes. + *

+ * Use fully qualified class names. + * + * @param classNames the list class names + * @return this operation instance + */ + public CompileKotlinOptions scriptTemplates(Collection classNames) { + scriptTemplates_.addAll(classNames); + return this; + } + + /** + * Enable verbose logging output which includes details of the compilation process. + * + * @param verbose {@code true} or {@code false} + * @return this operation instance + */ + public CompileKotlinOptions verbose(boolean verbose) { + verbose_ = verbose; + return this; + } + + /** + * Turn any warnings into a compilation error. + * + * @param wError {@code true} or {@code false} + * @return this operation instance + */ + public CompileKotlinOptions wError(boolean wError) { + wError_ = wError; + return this; + } +} diff --git a/src/main/java/rife/bld/extension/CompileKotlinPlugin.java b/src/main/java/rife/bld/extension/CompileKotlinPlugin.java new file mode 100644 index 0000000..bddafbf --- /dev/null +++ b/src/main/java/rife/bld/extension/CompileKotlinPlugin.java @@ -0,0 +1,40 @@ +/* + * Copyright 2023-2024 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 the known Kotlin compiler plugins match (regex) strings. + * + * @author Erik C. Thauvin + * @since 1.0 + */ +public enum CompileKotlinPlugin { + ALL_OPEN("^allopen-compiler-plugin-.*$"), + ASSIGNMENT("^assignment-compiler-plugin-.*$"), + KOTLIN_IMPORTS_DUMPER("^kotlin-imports-dumper-compiler-plugin-.*$"), + KOTLIN_SERIALIZATION("^kotlin-serialization-compiler-plugin-.*$"), + KOTLINX_SERIALIZATION("^kotlinx-serialization-compiler-plugin-.*$"), + LOMBOK("^lombok-compiler-plugin-.*$"), + NOARG("^noarg-compiler-plugin-.*$"), + SAM_WITH_RECEIVER("^sam-with-receiver-compiler-plugin-.*$"); + + public final String label; + + CompileKotlinPlugin(String label) { + this.label = label; + } +} diff --git a/src/main/java/rife/bld/extension/dokka/AnalysisPlatform.java b/src/main/java/rife/bld/extension/dokka/AnalysisPlatform.java new file mode 100644 index 0000000..dd6ff1a --- /dev/null +++ b/src/main/java/rife/bld/extension/dokka/AnalysisPlatform.java @@ -0,0 +1,27 @@ +/* + * Copyright 2023-2024 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.dokka; + +/** + * Dokka's analysis platforms. + * + * @author Erik C. Thauvin + * @since 1.0 + */ +public enum AnalysisPlatform { + JVM, JS, NATIVE, COMMON, ANDROID +} diff --git a/src/main/java/rife/bld/extension/dokka/DocumentedVisibility.java b/src/main/java/rife/bld/extension/dokka/DocumentedVisibility.java new file mode 100644 index 0000000..dae65a4 --- /dev/null +++ b/src/main/java/rife/bld/extension/dokka/DocumentedVisibility.java @@ -0,0 +1,27 @@ +/* + * Copyright 2023-2024 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.dokka; + +/** + * Dokka documented visibilities. + * + * @author Erik C. Thauvin + * @since 1.0 + */ +public enum DocumentedVisibility { + PUBLIC, PRIVATE, PROTECTED, INTERNAL, PACKAGE +} diff --git a/src/main/java/rife/bld/extension/dokka/DokkaOperation.java b/src/main/java/rife/bld/extension/dokka/DokkaOperation.java new file mode 100644 index 0000000..0b0936e --- /dev/null +++ b/src/main/java/rife/bld/extension/dokka/DokkaOperation.java @@ -0,0 +1,584 @@ +/* + * Copyright 2023-2024 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.dokka; + +import rife.bld.BaseProject; +import rife.bld.extension.CompileKotlinOperation; +import rife.bld.operations.AbstractProcessOperation; +import rife.tools.StringUtils; + +import java.io.File; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; + +import static rife.bld.extension.CompileKotlinOperation.isNotBlank; + +/** + * Builds documentation (javadoc, HTML, etc.) using Dokka. + * + * @author Erik C. Thauvin + * @since 1.0 + */ +@SuppressWarnings("PMD.AvoidThrowingRawExceptionTypes") +public class DokkaOperation extends AbstractProcessOperation { + private final static String GFM_PLUGIN_REGEXP = + "^.*(dokka-base|analysis-kotlin-descriptors|gfm-plugin|freemarker).*\\.jar$"; + private final static String HTML_PLUGIN_REGEXP = + "^.*(dokka-base|analysis-kotlin-descriptors|kotlinx-html-jvm|freemarker).*\\.jar$"; + private final static String JAVADOC_PLUGIN_REGEXP = + "^.*(dokka-base|analysis-kotlin-descriptors|javadoc-plugin|kotlin-as-java-plugin|korte-jvm).*\\.jar$"; + private final static String JEKYLL_PLUGIN_REGEXP = + "^.*(dokka-base|analysis-kotlin-descriptors|jekyll-plugin|gfm-plugin|freemarker).*\\.jar$"; + private final Logger LOGGER = Logger.getLogger(DokkaOperation.class.getName()); + private final Map globalLinks_ = new ConcurrentHashMap<>(); + private final Collection globalPackageOptions_ = new ArrayList<>(); + private final Collection globalSrcLinks_ = new ArrayList<>(); + private final Collection includes_ = new ArrayList<>(); + private final Map pluginConfiguration_ = new ConcurrentHashMap<>(); + private final Collection pluginsClasspath_ = new ArrayList<>(); + private boolean delayTemplateSubstitution_; + private boolean failOnWarning_; + private LoggingLevel loggingLevel_; + private String moduleName_; + private String moduleVersion_; + private boolean noSuppressObviousFunctions_; + private boolean offlineMode_; + private File outputDir_; + private BaseProject project_; + private SourceSet sourceSet_; + private boolean suppressInheritedMembers_; + + /** + * Sets the delay substitution of some elements. + *

+ * Used in incremental builds of multimodule projects. + * + * @param delayTemplateSubstitution the delay + * @return this operation instance + */ + public DokkaOperation delayTemplateSubstitution(Boolean delayTemplateSubstitution) { + delayTemplateSubstitution_ = delayTemplateSubstitution; + return this; + } + + /** + * Part of the {@link #execute execute} operation, constructs the command list to use for building the process. + * + * @since 1.5 + */ + @Override + protected List executeConstructProcessCommandList() { + if (project_ == null) { + throw new IllegalArgumentException("A project must be specified."); + } + + final List args = new ArrayList<>(); + + // java + args.add(javaTool()); + + var cli = CompileKotlinOperation.getJarList(project_.libBldDirectory(), "^.*dokka-cli.*\\.jar$"); + + if (cli.size() != 1) { + throw new RuntimeException("The dokka-cli JAR could not be found."); + } + + // -jar dokka-cli + args.add("-jar"); + args.add(cli.get(0)); + + // -pluginClasspath + if (!pluginsClasspath_.isEmpty()) { + args.add("-pluginsClasspath"); + args.add(String.join(";", pluginsClasspath_)); + } + + // -sourceSet + var sourceSetArgs = sourceSet_.args(); + if (sourceSetArgs.isEmpty()) { + throw new IllegalArgumentException("At least one sourceSet is required."); + } else { + args.add("-sourceSet"); + args.add(String.join(" ", sourceSet_.args())); + } + + // -outputDir + if (outputDir_ != null) { + if (!outputDir_.exists() && !outputDir_.mkdirs()) { + throw new RuntimeException("Could not create: " + outputDir_.getAbsolutePath()); + } + + args.add("-outputDir"); + args.add(outputDir_.getAbsolutePath()); + } + + // -delayTemplateSubstitution + if (delayTemplateSubstitution_) { + args.add("-delayTemplateSubstitution"); + args.add(String.valueOf(delayTemplateSubstitution_)); + } + + // -failOnWarning + if (failOnWarning_) { + args.add("-failOnWarning"); + args.add(String.valueOf(failOnWarning_)); + } + + // -globalLinks_ + if (!globalLinks_.isEmpty()) { + args.add("-globalLinks"); + var links = new ArrayList(); + globalLinks_.forEach((k, v) -> + links.add(String.format("%s^%s", k, v))); + args.add(String.join("^^", links)); + } + + // -globalPackageOptions + if (!globalPackageOptions_.isEmpty()) { + args.add("-globalPackageOptions"); + args.add(String.join(";", globalPackageOptions_)); + } + + // -globalSrcLinks + if (!globalSrcLinks_.isEmpty()) { + args.add("-globalSrcLinks_"); + args.add(String.join(";", globalSrcLinks_)); + } + + // -includes + if (!includes_.isEmpty()) { + args.add("-includes"); + args.add(String.join(";", includes_)); + } + + // -loggingLevel + if (loggingLevel_ != null) { + args.add("-loggingLevel"); + args.add(loggingLevel_.name().toLowerCase()); + } + + // -moduleName + if (isNotBlank(moduleName_)) { + args.add("-moduleName"); + args.add(moduleName_); + } + + // -moduleVersion + if (isNotBlank(moduleVersion_)) { + args.add("-moduleVersion"); + args.add(moduleVersion_); + } + + // -noSuppressObviousFunctions + if (noSuppressObviousFunctions_) { + args.add("-noSuppressObviousFunctions"); + args.add(String.valueOf(noSuppressObviousFunctions_)); + } + + // -offlineMode + if (offlineMode_) { + args.add("-offlineMode"); + args.add(String.valueOf(offlineMode_)); + } + + // -pluginConfiguration + if (!pluginConfiguration_.isEmpty()) { + args.add("-pluginConfiguration"); + var confs = new ArrayList(); + pluginConfiguration_.forEach((k, v) -> + confs.add(String.format("{%s}={%s}", StringUtils.encodeJson(k), StringUtils.encodeJson(v)))); + args.add(String.join("^^", confs)); + } + + // -suppressInheritedMembers + if (suppressInheritedMembers_) { + args.add("-suppressInheritedMembers"); + args.add(String.valueOf(suppressInheritedMembers_)); + } + + if (LOGGER.isLoggable(Level.FINE)) { + LOGGER.fine(String.join(" ", args)); + } + + return args; + } + + /** + * Configures the operation from a {@link BaseProject}. + *

+ * Sets the {@link #sourceSet sourceSet}, {@link SourceSet#jdkVersion jdkVersion} and {@link #moduleName moduleName} + * from the project. + * + * @param project the project to configure the operation from + */ + @Override + public DokkaOperation fromProject(BaseProject project) { + project_ = project; + sourceSet_ = new SourceSet().src(new File(project.srcMainDirectory(), "kotlin").getAbsolutePath()); + if (project.javaRelease() != null) { + sourceSet_ = sourceSet_.jdkVersion(project.javaRelease()); + } + moduleName_ = project.name(); + return this; + } + + /** + * Sets whether to fail documentation generation if Dokka has emitted a warning or an error. + *

+ * Whether to fail documentation generation if Dokka has emitted a warning or an error. The process waits until all + * errors and warnings have been emitted first. + *

+ * This setting works well with {@link SourceSet#reportUndocumented} + * + * @param failOnWarning {@code true} or {@code false} + * @return this operation instance + */ + public DokkaOperation failOnWarning(Boolean failOnWarning) { + failOnWarning_ = failOnWarning; + return this; + } + + /** + * Set the global external documentation links. + * + * @param url the external documentation URL + * @param packageListUrl the external documentation package list URL + * @return this operation instance + */ + public DokkaOperation globalLinks(String url, String packageListUrl) { + globalLinks_.put(url, packageListUrl); + return this; + } + + /** + * Set the global external documentation links. + * + * @param globalLinks the map of global links + * @return this operation instance + * @see #globalSrcLink(String...) #globalSrcLink(String...)#globalSrcLink(String...) + */ + public DokkaOperation globalLinks(Map globalLinks) { + globalLinks_.putAll(globalLinks); + return this; + } + + /** + * Sets the global list of package configurations. + *

+ * Using format: + *

    + *
  • matchingRegexp
  • + *
  • -deprecated
  • + *
  • -privateApi
  • + *
  • +warnUndocumented
  • + *
  • +suppress
  • + *
  • +visibility:PUBLIC
  • + *
  • ...
  • + *
+ * + * @param options ome pr more package configurations + * @return this operation instance + */ + public DokkaOperation globalPackageOptions(String... options) { + globalPackageOptions_.addAll(Arrays.asList(options)); + return this; + } + + /** + * Sets the global list of package configurations. + *

+ * Using format: + *

    + *
  • matchingRegexp
  • + *
  • -deprecated
  • + *
  • -privateApi
  • + *
  • +warnUndocumented
  • + *
  • +suppress
  • + *
  • +visibility:PUBLIC
  • + *
  • ...
  • + *
+ * + * @param options the list of package configurations + * @return this operation instance + */ + public DokkaOperation globalPackageOptions(Collection options) { + globalPackageOptions_.addAll(options); + return this; + } + + /** + * Sets the global mapping between a source directory and a Web service for browsing the code. + * + * @param links one or more links mapping + * @return this operation instance + */ + public DokkaOperation globalSrcLink(String... links) { + globalSrcLinks_.addAll(Arrays.asList(links)); + return this; + } + + /** + * Sets the global mapping between a source directory and a Web service for browsing the code. + * + * @param links the links mapping + * @return this operation instance + */ + public DokkaOperation globalSrcLink(Collection links) { + globalSrcLinks_.addAll(links); + return this; + } + + /** + * Sets the Markdown files that contain module and package documentation. + *

+ * The contents of specified files are parsed and embedded into documentation as module and package descriptions. + *

+ * This can be configured on per-package basis. + * + * @param files one or more files + * @return this operation instance + */ + public DokkaOperation includes(String... files) { + includes_.addAll(Arrays.asList(files)); + return this; + } + + /** + * Sets the Markdown files that contain module and package documentation. + *

+ * The contents of specified files are parsed and embedded into documentation as module and package descriptions. + *

+ * This can be configured on per-package basis. + * + * @param files the list of files + * @return this operation instance + */ + public DokkaOperation includes(Collection files) { + includes_.addAll(files); + return this; + } + + /** + * Sets the logging level. + * + * @param loggingLevel the logging level + * @return this operation instance + */ + public DokkaOperation loggingLevel(LoggingLevel loggingLevel) { + loggingLevel_ = loggingLevel; + return this; + } + + /** + * Sets the name of the project/module. Default is {@code root}. + *

+ * The display name used to refer to the module. It is used for the table of contents, navigation, logging, etc. + * + * @param moduleName the project/module name + * @return this operation instance + */ + public DokkaOperation moduleName(String moduleName) { + moduleName_ = moduleName; + return this; + } + + /** + * Set the documented version. + * + * @param version the version + * @return this operation instance + */ + public DokkaOperation moduleVersion(String version) { + moduleVersion_ = version; + return this; + } + + /** + * Sets whether to suppress obvious functions such as inherited from + * kotlin.Any and {@link java.lang.Object}. + *

+ * A function is considered to be obvious if it is: + *

    + *
  • Inherited from kotlin.Any, + * Kotlin.Enum, {@link java.lang.Object} + * or {@link java.lang.Enum}, such as {@code equals}, {@code hashCode}, {@code toString}. + *
  • Synthetic (generated by the compiler) and does not have any documentation, such as + * {@code dataClass.componentN} or {@code dataClass.copy}. + *
+ * + * @param noSuppressObviousFunctions {@code true} or {@code false} + * @return this operation instance + */ + public DokkaOperation noSuppressObviousFunctions(Boolean noSuppressObviousFunctions) { + noSuppressObviousFunctions_ = noSuppressObviousFunctions; + return this; + } + + /** + * Sets whether to resolve remote files/links over network. + *

+ * This includes package-lists used for generating external documentation links. For example, to make classes from + * the standard library clickable. + *

+ * Setting this to true can significantly speed up build times in certain cases, but can also worsen documentation + * quality and user experience. For example, by not resolving class/member links from your dependencies, including + * the standard library. + *

+ * Note: You can cache fetched files locally and provide them to Dokka as local paths. + * + * @param offlineMode the offline mode + * @return this operation instance + * @see SourceSet#externalDocumentationLinks(String, String) + */ + public DokkaOperation offlineMode(Boolean offlineMode) { + offlineMode_ = offlineMode; + return this; + } + + /** + * Sets the output directory path, {@code ./dokka} by default. + *

+ * The directory to where documentation is generated, regardless of output format. + * + * @param outputDir the output directory + * @return this operation instance + */ + public DokkaOperation outputDir(File outputDir) { + outputDir_ = outputDir; + return this; + } + + /** + * Sets the output directory path, {@code ./dokka} by default. + * + * @param outputDir the output directory + * @return this operation instance + */ + public DokkaOperation outputDir(String outputDir) { + outputDir_ = new File(outputDir); + return this; + } + + /** + * Sets the Dokka {@link OutputFormat output format}. + * + * @param format The {@link OutputFormat output format} + * @return this operation instance + */ + public DokkaOperation outputFormat(OutputFormat format) { + pluginsClasspath_.clear(); + if (format.equals(OutputFormat.JAVADOC)) { + pluginsClasspath_.addAll(CompileKotlinOperation.getJarList(project_.libBldDirectory(), + JAVADOC_PLUGIN_REGEXP)); + } else if (format.equals(OutputFormat.HTML)) { + pluginsClasspath_.addAll(CompileKotlinOperation.getJarList(project_.libBldDirectory(), + HTML_PLUGIN_REGEXP)); + } else if (format.equals(OutputFormat.MARKDOWN)) { + pluginsClasspath_.addAll(CompileKotlinOperation.getJarList(project_.libBldDirectory(), + GFM_PLUGIN_REGEXP)); + } else if (format.equals(OutputFormat.JEKYLL)) { + pluginsClasspath_.addAll(CompileKotlinOperation.getJarList(project_.libBldDirectory(), + JEKYLL_PLUGIN_REGEXP)); + } + return this; + } + + /** + * Sets the configuration for Dokka plugins. + * + * @param name The fully-qualified plugin name + * @param jsonConfiguration The plugin JSON configuration + * @return this operation instance + */ + public DokkaOperation pluginConfiguration(String name, String jsonConfiguration) { + pluginConfiguration_.put(name, jsonConfiguration); + return this; + } + + /** + * Sets the configuration for Dokka plugins. + * + * @param pluginConfiguration the map of configurations + * @return this operation instance + * @see #pluginConfiguration(String, String) + */ + public DokkaOperation pluginConfiguration(Map pluginConfiguration) { + pluginConfiguration_.putAll(pluginConfiguration); + return this; + } + + /** + * Sets the list of jars with Dokka plugins and their dependencies. + * + * @param jars one or more jars + * @return this operation instance + */ + public DokkaOperation pluginsClasspath(String... jars) { + pluginsClasspath_.addAll(Arrays.asList(jars)); + return this; + } + + /** + * Sets the list of jars with Dokka plugins and their dependencies. + * + * @param jars the list of jars + * @return this operation instance + */ + public DokkaOperation pluginsClasspath(Collection jars) { + pluginsClasspath_.addAll(jars); + return this; + } + + /** + * Clears the list of Dokka plugins. + * + * @param clear set to clear the list + * @return this operation instance + */ + public DokkaOperation pluginsClasspath(boolean clear) { + if (clear) { + pluginsClasspath_.clear(); + } + return this; + } + + /** + * Sets the configurations for a source set. + *

+ * Individual and additional configuration of Kotlin source sets. + * + * @param sourceSet the source set configurations + * @return this operation instance + */ + public DokkaOperation sourceSet(SourceSet sourceSet) { + sourceSet_ = sourceSet; + return this; + } + + /** + * Sets whether to suppress inherited members that aren't explicitly overridden in a given class. + * + * @param suppressInheritedMembers {@code true} or {@code false} + * @return this operation instance + */ + public DokkaOperation suppressInheritedMembers(Boolean suppressInheritedMembers) { + suppressInheritedMembers_ = suppressInheritedMembers; + return this; + } +} diff --git a/src/main/java/rife/bld/extension/dokka/LoggingLevel.java b/src/main/java/rife/bld/extension/dokka/LoggingLevel.java new file mode 100644 index 0000000..b493e11 --- /dev/null +++ b/src/main/java/rife/bld/extension/dokka/LoggingLevel.java @@ -0,0 +1,27 @@ +/* + * Copyright 2023-2024 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.dokka; + +/** + * Dokka logging levels. + * + * @author Erik C. Thauvin + * @since 1.0 + */ +public enum LoggingLevel { + DEBUG, PROGRESS, INFO, WARN, ERROR +} diff --git a/src/main/java/rife/bld/extension/dokka/OutputFormat.java b/src/main/java/rife/bld/extension/dokka/OutputFormat.java new file mode 100644 index 0000000..0d4a2c0 --- /dev/null +++ b/src/main/java/rife/bld/extension/dokka/OutputFormat.java @@ -0,0 +1,27 @@ +/* + * Copyright 2023-2024 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.dokka; + +/** + * Dokka output formats. + * + * @author Erik C. Thauvin + * @since 1.0 + */ +public enum OutputFormat { + JAVADOC, JEKYLL, HTML, MARKDOWN +} diff --git a/src/main/java/rife/bld/extension/dokka/SourceSet.java b/src/main/java/rife/bld/extension/dokka/SourceSet.java new file mode 100644 index 0000000..4a2dfb9 --- /dev/null +++ b/src/main/java/rife/bld/extension/dokka/SourceSet.java @@ -0,0 +1,626 @@ +/* + * Copyright 2023-2024 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.dokka; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Configuration for a Dokka source set. + * + * @author Erik C. Thauvin + * @since 1.0 + */ +public class SourceSet { + private static final String SEMICOLON = ";"; + private final Collection classpath_ = new ArrayList<>(); + private final Map dependentSourceSets_ = new ConcurrentHashMap<>(); + private final Collection documentedVisibilities_ = new ArrayList<>(); + private final Map externalDocumentationLinks_ = new ConcurrentHashMap<>(); + private final Collection includes_ = new ArrayList<>(); + private final Collection perPackageOptions_ = new ArrayList<>(); + private final Collection samples_ = new ArrayList<>(); + private final Map srcLinks_ = new ConcurrentHashMap<>(); + private final Collection src_ = new ArrayList<>(); + private final Collection suppressedFiles_ = new ArrayList<>(); + private AnalysisPlatform analysisPlatform_; + private String apiVersion_; + private String displayName_; + private int jdkVersion_; + private String languageVersion_; + private boolean noJdkLink_; + private boolean noSkipEmptyPackages_; + private boolean noStdlibLink_; + private boolean reportUndocumented_; + private boolean skipDeprecated_; + private String sourceSetName_; + + /** + * Sets the platform used for setting up analysis. Default is {@link AnalysisPlatform#JVM JVM} + *

+ * Platform to be used for setting up code analysis and {@code @sample} environment. + * + * @param analysisPlatform the analysis platform + * @return this operation instance + */ + public SourceSet analysisPlatform(AnalysisPlatform analysisPlatform) { + analysisPlatform_ = analysisPlatform; + return this; + } + + /** + * Sets the Kotlin API version used for setting up analysis and samples. + * + * @param apiVersion the api version + * @return this operation instance + */ + public SourceSet apiVersion(String apiVersion) { + apiVersion_ = apiVersion; + return this; + } + + /** + * Returns the formatted arguments. + * + * @return the arguments + */ + public List args() { + var args = new ArrayList(); + + // -analysisPlatform + if (analysisPlatform_ != null) { + args.add("-analysisPlatform"); + args.add(analysisPlatform_.name().toLowerCase()); + } + + // -apiVersion + if (apiVersion_ != null) { + args.add("-apiVersion"); + args.add(apiVersion_); + } + + // -classpath + if (!classpath_.isEmpty()) { + args.add("-classpath"); + args.add(String.join(SEMICOLON, classpath_)); + } + + // -dependentSourceSets + if (!dependentSourceSets_.isEmpty()) { + args.add("-dependentSourceSets"); + var deps = new ArrayList(); + dependentSourceSets_.forEach((k, v) -> deps.add(String.format("%s/%s", k, v))); + args.add(String.join(SEMICOLON, deps)); + } + + // -displayName + if (displayName_ != null) { + args.add("-displayName"); + args.add(displayName_); + } + + // -documentedVisibilities + if (!documentedVisibilities_.isEmpty()) { + args.add("-documentedVisibilities"); + var vis = new ArrayList(); + documentedVisibilities_.forEach(d -> vis.add(d.name().toLowerCase())); + args.add(String.join(SEMICOLON, vis)); + } + + // -externalDocumentationLinks + if (!externalDocumentationLinks_.isEmpty()) { + args.add("-externalDocumentationLinks"); + var links = new ArrayList(); + externalDocumentationLinks_.forEach((k, v) -> links.add(String.format("%s^%s", k, v))); + args.add(String.join("^^", links)); + } + + // -jdkVersion + if (jdkVersion_ > 0) { + args.add("-jdkVersion"); + args.add(String.valueOf(jdkVersion_)); + } + + // -includes + if (!includes_.isEmpty()) { + args.add("-includes"); + args.add(String.join(SEMICOLON, includes_)); + } + + // -languageVersion + if (languageVersion_ != null) { + args.add("-languageVersion"); + args.add(languageVersion_); + } + + // -noJdkLink + if (noJdkLink_) { + args.add("-noJdkLink"); + args.add(String.valueOf(noJdkLink_)); + } + + // -noSkipEmptyPackages + if (noSkipEmptyPackages_) { + args.add("-noSkipEmptyPackages"); + args.add(String.valueOf(noSkipEmptyPackages_)); + } + + // -noStdlibLink + if (noStdlibLink_) { + args.add("-noStdlibLink"); + args.add(String.valueOf(noStdlibLink_)); + } + + // -reportUndocumented + if (reportUndocumented_) { + args.add("-reportUndocumented"); + args.add(String.valueOf(reportUndocumented_)); + } + + // -perPackageOptions + if (!perPackageOptions_.isEmpty()) { + args.add("-perPackageOptions"); + args.add(String.join(SEMICOLON, perPackageOptions_)); + } + + // -samples + if (!samples_.isEmpty()) { + args.add("-samples"); + args.add(String.join(SEMICOLON, samples_)); + } + + // -skipDeprecated + if (skipDeprecated_) { + args.add("-skipDeprecated"); + args.add(String.valueOf(skipDeprecated_)); + } + + // -src + if (!src_.isEmpty()) { + args.add("-src"); + args.add(String.join(SEMICOLON, src_)); + } + + // -srcLink + if (!srcLinks_.isEmpty()) { + args.add("-srcLink"); + var links = new ArrayList(); + srcLinks_.forEach((k, v) -> links.add(String.format("%s=%s", k, v))); + args.add(String.join(SEMICOLON, links)); + } + + // -sourceSetName + if (sourceSetName_ != null) { + args.add("-sourceSetName"); + args.add(sourceSetName_); + } + + // -suppressedFiles + if (!suppressedFiles_.isEmpty()) { + args.add("-suppressedFiles"); + args.add(String.join(SEMICOLON, suppressedFiles_)); + } + + return args; + } + + /** + * Sets classpath for analysis and interactive samples. + *

+ * This is useful if some types that come from dependencies are not resolved/picked up automatically. + *

+ * This option accepts both {@code .jar} and {@code .klib} files. + * + * @param classpath one or more classpath + * @return this operation instance + */ + public SourceSet classpath(String... classpath) { + classpath_.addAll(Arrays.asList(classpath)); + return this; + } + + /** + * Sets classpath for analysis and interactive samples. + *

+ * This is useful if some types that come from dependencies are not resolved/picked up automatically. + *

+ * This option accepts both {@code .jar} and {@code .klib} files. + * + * @param classpath the list of classpath + * @return this operation instance + */ + public SourceSet classpath(Collection classpath) { + classpath_.addAll(classpath); + return this; + } + + /** + * Sets the names of dependent source sets. + * + * @param moduleName the module name + * @param sourceSetName the source set name + * @return this operation instance + */ + public SourceSet dependentSourceSets(String moduleName, String sourceSetName) { + dependentSourceSets_.put(moduleName, sourceSetName); + return this; + } + + /** + * Sets the names of dependent source sets. + * + * @param dependentSourceSets the map of dependent source set names + * @return this operation instance + * @see #dependentSourceSets(String, String) + */ + public SourceSet dependentSourceSets(Map dependentSourceSets) { + dependentSourceSets_.putAll(dependentSourceSets); + return this; + } + + /** + * Sets the display name of the source set, used both internally and externally. + *

+ * The name is used both externally (for example, the source set name is visible to documentation readers) and + * internally (for example, for logging messages of {@link #reportUndocumented reportUndocumented}). + *

+ * The platform name can be used if you don't have a better alternative. + * + * @param displayName the display name + * @return this operation instance + */ + public SourceSet displayName(String displayName) { + displayName_ = displayName; + return this; + } + + /** + * Sets visibilities to be documented. + *

+ * This can be used if you want to document protected/internal/private declarations, as well as if you want to + * exclude public declarations and only document internal API. + *

+ * This can be configured on per-package basis. + * + * @param visibilities one or more visibilities + * @return this operation instance + */ + public SourceSet documentedVisibilities(DocumentedVisibility... visibilities) { + documentedVisibilities_.addAll(Arrays.asList(visibilities)); + return this; + } + + /** + * Sets the external documentation links. + *

+ * A set of parameters for external documentation links that is applied only for this source set. + * + * @param url the external documentation URL + * @param packageListUrl the external documentation package list URL + * @return this operation instance + */ + public SourceSet externalDocumentationLinks(String url, String packageListUrl) { + externalDocumentationLinks_.put(url, packageListUrl); + return this; + } + + /** + * Sets the external documentation links. + *

+ * A set of parameters for external documentation links that is applied only for this source set. + * + * @param externalDocumentationLinks the map of external documentation links + * @return this operation instance + * @see #externalDocumentationLinks(String, String) + */ + public SourceSet externalDocumentationLinks(Map externalDocumentationLinks) { + externalDocumentationLinks_.putAll(externalDocumentationLinks); + return this; + } + + /** + * Sets the Markdown files that contain module and package documentation. + *

+ * A list of Markdown files that contain module and package documentation. + *

+ * The contents of the specified files are parsed and embedded into documentation as module and package + * descriptions. + * + * @param files one or more files + * @return this operation instance + */ + public SourceSet includes(String... files) { + includes_.addAll(Arrays.asList(files)); + return this; + } + + /** + * Sets the Markdown files that contain module and package documentation. + *

+ * A list of Markdown files that contain module and package documentation. + *

+ * The contents of the specified files are parsed and embedded into documentation as module and package + * descriptions. + * + * @param files the list of files + * @return this operation instance + */ + public SourceSet includes(Collection files) { + includes_.addAll(files); + return this; + } + + /** + * Sets the version of JDK to use for linking to JDK Javadocs. + *

+ * The JDK version to use when generating external documentation links for Java types. + *

+ * For example, if you use {@link java.util.UUID} in some public declaration signature, and this option is set to 8, + * Dokka generates an external documentation link to JDK 8 Javadocs for it. + * + * @param jdkVersion the JDK version + * @return this operation instance + */ + public SourceSet jdkVersion(int jdkVersion) { + jdkVersion_ = jdkVersion; + return this; + } + + /** + * Sets the language version used for setting up analysis and samples. + * + * @param languageVersion the language version + * @return this operation instance + */ + public SourceSet languageVersion(String languageVersion) { + languageVersion_ = languageVersion; + return this; + } + + /** + * Sets whether to generate links to JDK Javadocs. + *

+ * Whether to generate external documentation links to JDK's Javadocs. + *

+ * The version of JDK Javadocs is determined by the {@link #jdkVersion jdkVersion} option. + *

+ * Note: Links are generated when noJdkLink is set to false. + * + * @param noJdkLink {@code true} or {@code false} + * @return this operation instance + */ + public SourceSet noJdkLink(Boolean noJdkLink) { + noJdkLink_ = noJdkLink; + return this; + } + + /** + * Sets whether to create pages for empty packages. + *

+ * Whether to skip packages that contain no visible declarations after various filters have been applied. + * + * @param noSkipEmptyPackages {@code true} or {@code false} + * @return this operation instance + */ + public SourceSet noSkipEmptyPackages(boolean noSkipEmptyPackages) { + noSkipEmptyPackages_ = noSkipEmptyPackages; + return this; + } + + /** + * Sets whether to generate links to Standard library. + *

+ * Whether to generate external documentation links that lead to the API reference documentation of Kotlin's + * standard library. + *

+ * Note: Links are generated when noStdLibLink is set to {@code false}. + * + * @param noStdlibLink {@code true} or {@code false} + * @return this operation instance + */ + public SourceSet noStdlibLink(Boolean noStdlibLink) { + noStdlibLink_ = noStdlibLink; + return this; + } + + /** + * Set the list of package source set configuration. + *

+ * A set of parameters specific to matched packages within this source set. + *

+ * Using format: + *

    + *
  • matchingRegexp
  • + *
  • -deprecated
  • + *
  • -privateApi
  • + *
  • +warnUndocumented
  • + *
  • +suppress
  • + *
  • +visibility:PUBLIC
  • + *
  • ...
  • + *
+ * + * @param perPackageOptions the list of per package options + * @return this operation instance + */ + public SourceSet perPackageOptions(Collection perPackageOptions) { + perPackageOptions_.addAll(perPackageOptions); + return this; + } + + /** + * Set the list of package source set configuration. + *

+ * A set of parameters specific to matched packages within this source set. + *

+ * Using format: + *

    + *
  • matchingRegexp
  • + *
  • -deprecated
  • + *
  • -privateApi
  • + *
  • +warnUndocumented
  • + *
  • +suppress
  • + *
  • +visibility:PUBLIC
  • + *
  • ...
  • + *
+ * + * @param perPackageOptions the list of per package options + * @return this operation instance + */ + public SourceSet perPackageOptions(String... perPackageOptions) { + perPackageOptions_.addAll(List.of(perPackageOptions)); + return this; + } + + /** + * Sets whether to report undocumented declarations. + *

+ * Whether to emit warnings about visible undocumented declarations, that is declarations without KDocs after they + * have been filtered by documentedVisibilities and other filters. + *

+ * This setting works well with {@link DokkaOperation#failOnWarning}. + *

+ * This can be configured on per-package basis. + * + * @param reportUndocumented {@code true} or {@code false} + * @return this operation instance + */ + public SourceSet reportUndocumented(Boolean reportUndocumented) { + reportUndocumented_ = reportUndocumented; + return this; + } + + /** + * Set the list of directories or files that contain sample functions. + *

+ * A list of directories or files that contain sample functions which are referenced via the {@code @sample} KDoc + * tag. + * + * @param samples the list of samples + * @return this operation instance + */ + public SourceSet samples(Collection samples) { + samples_.addAll(samples); + return this; + } + + /** + * Set the list of directories or files that contain sample functions. + *

+ * A list of directories or files that contain sample functions which are referenced via the {@code @sample} KDoc + * tag. + * + * @param samples nne or more samples + * @return this operation instance + */ + public SourceSet samples(String... samples) { + samples_.addAll(List.of(samples)); + return this; + } + + /** + * Sets whether to skip deprecated declarations. + *

+ * Whether to document declarations annotated with {@code @Deprecated}. + *

+ * This can be configured on per-package basis. + * + * @param skipDeprecated {@code true} or {@code false} + * @return this operation instance + */ + public SourceSet skipDeprecated(boolean skipDeprecated) { + skipDeprecated_ = skipDeprecated; + return this; + } + + /** + * Sets the name of the source set. Default is {@code main}. + * + * @param sourceSetName the source set name. + * @return this operation instance + */ + public SourceSet sourceSetName(String sourceSetName) { + sourceSetName_ = sourceSetName; + return this; + } + + /** + * Sets the source code roots to be analyzed and documented. + *

+ * The source code roots to be analyzed and documented. Acceptable inputs are directories and individual + * {@code .kt} / {@code .java} files. + * + * @param src the list of source code roots + * @return this operation instance + */ + public SourceSet src(Collection src) { + src_.addAll(src); + return this; + } + + /** + * Sets the source code roots to be analyzed and documented. + *

+ * The source code roots to be analyzed and documented. Acceptable inputs are directories and individual + * {@code .kt} / {@code .java} files. + * + * @param src pne ore moe source code roots + * @return this operation instance + */ + public SourceSet src(String... src) { + src_.addAll(List.of(src)); + return this; + } + + /** + * Sets the mapping between a source directory and a Web service for browsing the code. + * + * @param srcPath the source path + * @param remotePath the remote path + * @param lineSuffix the line suffix + * @return this operation instance + */ + public SourceSet srcLink(String srcPath, String remotePath, String lineSuffix) { + srcLinks_.put(srcPath, remotePath + lineSuffix); + return this; + } + + /** + * Sets the paths to files to be suppressed. + *

+ * The files to be suppressed when generating documentation. + * + * @param suppressedFiles the list of suppressed files + * @return this operation instance + */ + public SourceSet suppressedFiles(Collection suppressedFiles) { + suppressedFiles_.addAll(suppressedFiles); + return this; + } + + /** + * Sets the paths to files to be suppressed. + *

+ * The files to be suppressed when generating documentation. + * + * @param suppressedFiles one or moe suppressed files + * @return this operation instance + */ + public SourceSet suppressedFiles(String... suppressedFiles) { + suppressedFiles_.addAll(Arrays.asList(suppressedFiles)); + return this; + } +} diff --git a/src/main/java/rife/bld/extension/kotlin/CompileOptions.java b/src/main/java/rife/bld/extension/kotlin/CompileOptions.java deleted file mode 100644 index e43adc8..0000000 --- a/src/main/java/rife/bld/extension/kotlin/CompileOptions.java +++ /dev/null @@ -1,1087 +0,0 @@ -/* - * 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.kotlin; - -import rife.bld.extension.CompileKotlinOperation; -import rife.bld.operations.AbstractToolProviderOperation; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.file.Files; -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; - -import static rife.bld.extension.CompileKotlinOperation.isNotBlank; - -/** - * Configuration for the Kotlin compiler options. - * - * @author Erik C. Thauvin - * @since 1.0 - */ -public class CompileOptions { - private static final Logger LOGGER = Logger.getLogger(CompileOptions.class.getName()); - private final Collection advancedOptions_ = new ArrayList<>(); - private final Collection argFile_ = new ArrayList<>(); - private final Collection classpath_ = new ArrayList<>(); - private final Collection optIn_ = new ArrayList<>(); - private final Collection options_ = new ArrayList<>(); - private final Collection plugin_ = new ArrayList<>(); - private final Collection scriptTemplates_ = new ArrayList<>(); - private String apiVersion_; - private String expression_; - private boolean includeRuntime_; - private boolean javaParameters_; - private File jdkHome_; - private String jdkRelease_; - private String jvmTarget_; - private File kotlinHome_; - private String languageVersion_; - private String moduleName_; - private boolean noJdk_; - private boolean noReflect_; - private boolean noStdLib_; - private boolean noWarn_; - private File path_; - private boolean progressive_; - private boolean verbose_; - private boolean wError_; - private boolean wExtra_; - - /** - * Specify advanced compiler options. - * - * @param options one or more advanced options - * @return this operation instance - */ - public CompileOptions advancedOptions(String... options) { - return advancedOptions(List.of(options)); - } - - /** - * Specify advanced compiler options. - * - * @param options the compiler options - * @return this operation instance - */ - public CompileOptions advancedOptions(Collection options) { - advancedOptions_.addAll(options); - return this; - } - - /** - * Retrieves advanced compiler options. - * - * @return the advanced compiler options - */ - public Collection advancedOptions() { - return advancedOptions_; - } - - /** - * Retrieves the version of Kotlin bundled libraries. - * - * @return the API version - */ - public String apiVersion() { - return apiVersion_; - } - - /** - * Allow using declarations only from the specified version of Kotlin bundled libraries. - * - * @param version the API version - * @return this operation instance - */ - public CompileOptions apiVersion(String version) { - apiVersion_ = version; - return this; - } - - /** - * Allow using declarations only from the specified version of Kotlin bundled libraries. - * - * @param version the API version - * @return this operation instance - */ - public CompileOptions apiVersion(int version) { - return apiVersion(String.valueOf(version)); - } - - /** - * Read the compiler options from the given files. - *

- * Such a file can contain compiler options with values and paths to the source files. - * Options and paths should be separated by whitespaces. For example: - *

    - *
  • {@code -include-runtime -d hello.jar hello.kt}
  • - *
- * To pass values that contain whitespaces, surround them with single ({@code '}) or double ({@code "}) quotes. - * If a value contains quotation marks in it, escape them with a backslash (\). - *
    - *
  • {@code -include-runtime -d 'My folder'}
  • - *
- * If the files reside in locations different from the current directory, use relative paths. - * - * @param files one or more files - * @return this operation instance - * @see #argFileStrings(Collection) - */ - public CompileOptions argFile(String... files) { - return argFileStrings(List.of(files)); - } - - /** - * Read the compiler options from the given files. - * - * @param files the compiler options files - * @return this operation instance - * @see #argFile(File...) - */ - public CompileOptions argFile(Collection files) { - argFile_.addAll(files); - return this; - } - - /** - * Read the compiler options from the given files. - *

- * Such a file can contain compiler options with values and paths to the source files. - * Options and paths should be separated by whitespaces. For example: - *

    - *
  • {@code -include-runtime -d hello.jar hello.kt}
  • - *
- * To pass values that contain whitespaces, surround them with single ({@code '}) or double ({@code "}) quotes. - * If a value contains quotation marks in it, escape them with a backslash (\). - *
    - *
  • {@code -include-runtime -d 'My folder'}
  • - *
- * If the files reside in locations different from the current directory, use relative paths. - * - * @param files one or more files - * @return this operation instance - * @see #argFile(Collection) - */ - public CompileOptions argFile(File... files) { - return argFile(List.of(files)); - } - - /** - * Read the compiler options from the given files. - *

- * Such a file can contain compiler options with values and paths to the source files. - * Options and paths should be separated by whitespaces. For example: - *

    - *
  • {@code -include-runtime -d hello.jar hello.kt}
  • - *
- * To pass values that contain whitespaces, surround them with single ({@code '}) or double ({@code "}) quotes. - * If a value contains quotation marks in it, escape them with a backslash (\). - *
    - *
  • {@code -include-runtime -d 'My folder'}
  • - *
- * If the files reside in locations different from the current directory, use relative paths. - * - * @param files one or more files - * @return this operation instance - * @see #argFilePaths(Collection) - */ - public CompileOptions argFile(Path... files) { - return argFilePaths(List.of(files)); - } - - /** - * Retrieves the files containing compiler options. - * - * @return the compiler options files - */ - public Collection argFile() { - return argFile_; - } - - /** - * Read the compiler options from the given files. - * - * @param files the compiler options files - * @return this operation instance - * @see #argFile(Path...) - */ - public CompileOptions argFilePaths(Collection files) { - return argFile(files.stream().map(Path::toFile).toList()); - } - - /** - * Read the compiler options from the given files. - * - * @param files the compiler options files - * @return this operation instance - * @see #argFile(String...) - */ - public CompileOptions argFileStrings(Collection files) { - return argFile(files.stream().map(File::new).toList()); - } - - /** - * Returns the formatted arguments. - * - * @return the arguments - */ - public List args() { - var args = new ArrayList(); - - // api-version - if (isNotBlank(apiVersion_)) { - args.add("-api-version"); - args.add(apiVersion_); - } - - // @argfile - if (!argFile_.isEmpty()) { - argFile_.forEach(f -> { - if (f.exists()) { - try { - try (var reader = Files.newBufferedReader(f.toPath(), Charset.defaultCharset())) { - var tokenizer = new AbstractToolProviderOperation.CommandLineTokenizer(reader); - String token; - while ((token = tokenizer.nextToken()) != null) { - args.add(token); - } - } - } catch (IOException e) { - if (LOGGER.isLoggable(Level.WARNING)) { - LOGGER.log(Level.WARNING, "Could not read: " + f.getAbsolutePath(), e); - } - } - } else { - if (LOGGER.isLoggable(Level.WARNING)) { - LOGGER.warning("File not found: " + f.getAbsolutePath()); - } - } - }); - } - - // expression - if (isNotBlank(expression_)) { - args.add("-expression"); - args.add(expression_); - } - - // java-parameters - if (javaParameters_) { - args.add("-java-parameters"); - } - - // jvm-target - if (isNotBlank(jvmTarget_)) { - args.add("-jvm-target"); - args.add(jvmTarget_); - } - - // include-runtime - if (includeRuntime_) { - args.add("-include-runtime"); - } - - // jdk-home - if (jdkHome_ != null) { - args.add("-jdk-home"); - args.add(jdkHome_.getAbsolutePath()); - } - - // jdk-release - if (isNotBlank(jdkRelease_)) { - args.add("-Xjdk-release=" + jdkRelease_); - } - - // kotlin-home - if (kotlinHome_ != null) { - args.add("-kotlin-home"); - args.add(kotlinHome_.getAbsolutePath()); - } - - // language-version - if (isNotBlank(languageVersion_)) { - args.add("-language-version"); - args.add(languageVersion_); - } - - // module-name - if (isNotBlank(moduleName_)) { - args.add("-module-name"); - args.add(moduleName_); - } - - // no-jdk - if (noJdk_) { - args.add("-no-jdk"); - } - - // no-reflect - if (noReflect_) { - args.add("-no-reflect"); - } - - // no-std-lib - if (noStdLib_) { - args.add("-no-stdlib"); - } - - // no-warn - if (noWarn_) { - args.add("-nowarn"); - } - - // opt-in - optIn_.stream().filter(CompileKotlinOperation::isNotBlank).forEach(o -> { - args.add("-opt-in"); - args.add(o); - }); - - // options - if (!options_.isEmpty()) { - args.addAll(options_); - } - - // path - if (path_ != null) { - args.add("-d"); - args.add(path_.getAbsolutePath()); - } - - // plugin - plugin_.stream().filter(CompileKotlinOperation::isNotBlank).forEach(p -> { - args.add("-P"); - args.add("plugin:" + p); - }); - - // progressive - if (progressive_) { - args.add("-progressive"); - } - - // script-templates - if (!scriptTemplates_.isEmpty()) { - args.add("-script-templates"); - args.add(String.join(",", scriptTemplates_)); - } - - // verbose - if (verbose_) { - args.add("-verbose"); - } - - // Werror - if (wError_) { - args.add("-Werror"); - } - - // Wextra - if (wExtra_) { - args.add("-Wextra"); - } - - // advanced options (X) - if (!advancedOptions_.isEmpty()) { - advancedOptions_.forEach(it -> { - if (it.startsWith("-X")) { - args.add(it); - } else { - args.add("-X" + it); - } - }); - } - - return args; - } - - /** - * Search for class files in the specified paths. - *

- * The classpath can contain file and directory paths, ZIP, or JAR files. - * - * @param paths one pr more paths - * @return this operation instance - * @see #classpathStrings(Collection) - */ - public CompileOptions classpath(String... paths) { - return classpathStrings(List.of(paths)); - } - - /** - * Search for class files in the specified paths. - *

- * The classpath can contain file and directory paths, ZIP, or JAR files. - * - * @param paths one or more path - * @return this operation instance - * @see #classpath(Collection) - */ - public CompileOptions classpath(File... paths) { - return classpath(List.of(paths)); - } - - /** - * Search for class files in the specified paths. - *

- * The classpath can contain file and directory paths, ZIP, or JAR files. - * - * @param paths one or more path - * @return this operation instance - * @see #classpathPaths(Collection) - */ - public CompileOptions classpath(Path... paths) { - return classpathPaths(List.of(paths)); - } - - /** - * Search for class files in the specified paths. - *

- * The classpath can contain file and directory paths, ZIP, or JAR files. - * - * @param paths the search paths - * @return this operation instance - * @see #classpath(File...) - */ - public CompileOptions classpath(Collection paths) { - classpath_.addAll(paths); - return this; - } - - /** - * Retrieves the class files classpath. - * - * @return the class files classpath - */ - public Collection classpath() { - return classpath_; - } - - /** - * Search for class files in the specified paths. - *

- * The classpath can contain file and directory paths, ZIP, or JAR files. - * - * @param paths one pr more paths - * @return this operation instance - * @see #classpath(Path...) - */ - public CompileOptions classpathPaths(Collection paths) { - return classpath(paths.stream().map(Path::toFile).toList()); - } - - /** - * Search for class files in the specified paths. - *

- * The classpath can contain file and directory paths, ZIP, or JAR files. - * - * @param paths one pr more paths - * @return this operation instance - * @see #classpath(String...) - */ - public CompileOptions classpathStrings(Collection paths) { - return classpath(paths.stream().map(File::new).toList()); - } - - /** - * Retrieves the string to evaluate as a Kotlin script. - * - * @return the expression - */ - public String expression() { - return expression_; - } - - /** - * Evaluate the given string as a Kotlin script. - * - * @param expression the expression - * @return this operation instance - */ - public CompileOptions expression(String expression) { - expression_ = expression; - return this; - } - - /** - * Indicates whether the {@link #jdkRelease(String) jdkRelease} was set. - * - * @return {@code true} if the release was set; or {@code false} otherwise - */ - public boolean hasRelease() { - return jdkRelease_ != null; - } - - /** - * Include the Kotlin runtime into the resulting JAR file. Makes the resulting archive runnable on any Java-enabled - * environment. - * - * @param includeRuntime {@code true} or {@code false} - * @return this operation instance - */ - public CompileOptions includeRuntime(boolean includeRuntime) { - includeRuntime_ = includeRuntime; - return this; - } - - /** - * Indicates whether the {@link #includeRuntime(boolean)} was set. - * - * @return {@code true} or {@code false} - */ - public boolean isIncludeRuntime() { - return includeRuntime_; - } - - /** - * Indicates whether {@link #javaParameters(boolean)} was set. - * - * @return {@code true} or {@code false} - */ - public boolean isJavaParameters() { - return javaParameters_; - } - - /** - * Indicates whether {@link #noJdk(boolean) noJdk} was set. - * - * @return {@code true} or {@code false} - */ - public boolean isNoJdk() { - return noJdk_; - } - - /** - * Indicates whether {@link #noReflect(boolean) noRflect} was set. - * - * @return {@code true} or {@code false} - */ - public boolean isNoReflect() { - return noReflect_; - } - - /** - * Indicates whether {@link #noStdLib(boolean) noStdLib} +was set. - * - * @return {@code true} or {@code false} - */ - public boolean isNoStdLib() { - return noStdLib_; - } - - /** - * Indicates whether {@link #noWarn(boolean) noWarn} was set. - * - * @return {@code true} or {@code false} - */ - public boolean isNoWarn() { - return noWarn_; - } - - /** - * Indicates whether {@link #progressive(boolean) progressive} was set. - * - * @return {@code true} or {@code false} - */ - public boolean isProgressive() { - return progressive_; - } - - /** - * Indicates whether {@link #verbose(boolean)} was set. - * - * @return {@code true} if verbose was set; or {@code false} otherwise - */ - public boolean isVerbose() { - return verbose_; - } - - /** - * Indicates whether warnings are turned into a compilation error. - * - * @return {@code true} or {@code false} - */ - public boolean isWError() { - return wError_; - } - - /** - * Indicates whether additional declaration, expression, and type compiler checks emit warnings. - * - * @return {@code true} or {@code false} - */ - public boolean isWExtra() { - return wExtra_; - } - - /** - * Generate metadata for Java 1.8 reflection on method parameters. - * - * @param javaParameters {@code true} or {@code false} - * @return this operation instance - */ - public CompileOptions javaParameters(boolean javaParameters) { - javaParameters_ = javaParameters; - return this; - } - - /** - * Use a custom JDK home directory to include into the classpath if it differs from the default {@code JAVA_HOME}. - * - * @param jdkHome the JDK home path - * @return this operation instance - */ - public CompileOptions jdkHome(File jdkHome) { - jdkHome_ = jdkHome; - return this; - } - - /** - * Use a custom JDK home directory to include into the classpath if it differs from the default {@code JAVA_HOME}. - * - * @param jdkHome the JDK home path - * @return this operation instance - */ - public CompileOptions jdkHome(String jdkHome) { - return jdkHome(new File(jdkHome)); - } - - /** - * Use a custom JDK home directory to include into the classpath if it differs from the default {@code JAVA_HOME}. - * - * @param jdkHome the JDK home path - * @return this operation instance - */ - public CompileOptions jdkHome(Path jdkHome) { - return jdkHome(jdkHome.toFile()); - } - - /** - * Retrieves the custom JDK home directory. - * - * @return the JDK home path. - */ - public File jdkHome() { - return jdkHome_; - } - - /** - * Return the specified JDK API version. - * - * @return the API version - */ - public String jdkRelease() { - return jdkRelease_; - } - - /** - * Compile against the specified JDK API version. - *

- * Limit the API of the JDK in the classpath to the specified Java version. Automatically sets - * {@link #jvmTarget(String) JVM target} version. - *

- * Possible values are 1.8, 9, 10, ..., 23. The default value is 1.8. - * - * @param version the target version - * @return this operation instance - */ - public CompileOptions jdkRelease(String version) { - jdkRelease_ = version; - return this; - } - - /** - * Compile against the specified JDK API version. - *

- * Limit the API of the JDK in the classpath to the specified Java version. Automatically sets - * {@link #jvmTarget(String) JVM target} version. - * - * @param version the target version - * @return this operation instance - * @see #jdkRelease(String) - */ - public CompileOptions jdkRelease(int version) { - return jdkRelease(String.valueOf(version)); - } - - /** - * Specify the target version of the generated JVM bytecode. - * - * @param target the target version - * @return this operation instance - * @see #jvmTarget(String) - */ - public CompileOptions jvmTarget(int target) { - return jvmTarget(String.valueOf(target)); - } - - /** - * Specify the target version of the generated JVM bytecode. - *

- * Possible values are 1.8, 9, 10, ..., 23. The default value is 1.8. - * - * @param target the target version - * @return this operation instance - */ - public CompileOptions jvmTarget(String target) { - jvmTarget_ = target; - return this; - } - - /** - * Retrieves the target version of the generated JVM bytecode. - * - * @return the target version - */ - public String jvmTarget() { - return jvmTarget_; - } - - /** - * Specify a custom path to the Kotlin compiler used for the discovery of runtime libraries. - * - * @param path the Kotlin home path - * @return this operation instance - */ - public CompileOptions kotlinHome(File path) { - kotlinHome_ = path; - return this; - } - - /** - * Retrieves the custom path of the Kotlin compiler. - * - * @return the Kotlin home path - */ - public File kotlinHome() { - return kotlinHome_; - } - - /** - * Specify a custom path to the Kotlin compiler used for the discovery of runtime libraries. - * - * @param path the Kotlin home path - * @return this operation instance - */ - public CompileOptions kotlinHome(Path path) { - return kotlinHome(path.toFile()); - } - - /** - * Specify a custom path to the Kotlin compiler used for the discovery of runtime libraries. - * - * @param path the Kotlin home path - * @return this operation instance - */ - public CompileOptions kotlinHome(String path) { - return kotlinHome(new File(path)); - } - - /** - * Provide source compatibility with the specified version of Kotlin. - * - * @param version the language version - * @return this operation instance - */ - public CompileOptions languageVersion(String version) { - languageVersion_ = version; - return this; - } - - /** - * Retrieves the {@link #languageVersion(String) language version}. - * - * @return the language version - */ - public String languageVersion() { - return languageVersion_; - } - - /** - * Set a custom name for the generated {@code .kotlin_module} file. - * - * @param name the module name - * @return this operation instance - */ - public CompileOptions moduleName(String name) { - moduleName_ = name; - return this; - } - - /** - * Retrieves the {@link #moduleName(String) module name}. - * - * @return the module name - */ - public String moduleName() { - return moduleName_; - } - - /** - * Don't automatically include the Java runtime into the classpath. - * - * @param noJdk {@code true} or {@code false} - * @return this operation instance - */ - public CompileOptions noJdk(boolean noJdk) { - noJdk_ = noJdk; - return this; - } - - /** - * Don't automatically include the Kotlin reflection ({@code kotlin-reflect.jar}) into the classpath. - * - * @param noReflect {@code true} or {@code false} - * @return this operation instance - */ - public CompileOptions noReflect(boolean noReflect) { - noReflect_ = noReflect; - return this; - } - - /** - * Don't automatically include the Kotlin/JVM stdlib ({@code kotlin-stdlib.jar}) and Kotlin reflection - * ({@code kotlin-reflect.jar}) into the classpath. - * - * @param noStdLib {@code true} or {@code false} - * @return this operation instance - */ - public CompileOptions noStdLib(boolean noStdLib) { - noStdLib_ = noStdLib; - return this; - } - - /** - * Suppress the compiler from displaying warnings during compilation. - * - * @param noWarn {@code true} or {@code false} - * @return this operation instance - */ - public CompileOptions noWarn(boolean noWarn) { - noWarn_ = noWarn; - return this; - } - - /** - * Enable usages of API that requires opt-in with a requirement annotation with the given fully qualified name. - * - * @param annotations one or more annotation names - * @return this operation instance - */ - public CompileOptions optIn(String... annotations) { - return optIn(List.of(annotations)); - } - - /** - * Retrieves the opt-in fully qualified names. - * - * @return the fully qualified names - */ - public Collection optIn() { - return optIn_; - } - - /** - * Enable usages of API that requires opt-in with a requirement annotation with the given fully qualified name. - * - * @param annotations the annotation names - * @return this operation instance - */ - public CompileOptions optIn(Collection annotations) { - optIn_.addAll(annotations); - return this; - } - - /** - * Specify additional compiler options. - * - * @param options one or more compiler options - * @return this operation instance - */ - public CompileOptions options(String... options) { - return options(List.of(options)); - } - - /** - * Retrieves additional compiler options. - * - * @return the compiler options - */ - public Collection options() { - return options_; - } - - /** - * Specify additional compiler options. - * - * @param options the compiler options - * @return this operation instance - */ - public CompileOptions options(Collection options) { - options_.addAll(options); - return this; - } - - /** - * Place the generated class files into the specified location. - *

- * The location can be a directory, a ZIP, or a JAR file. - * - * @param path the location path - * @return this operation instance - */ - public CompileOptions path(File path) { - path_ = path; - return this; - } - - /** - * Retrieves the location to place generated class files into. - * - * @return the location path. - */ - public File path() { - return path_; - } - - /** - * Place the generated class files into the specified location. - *

- * The location can be a directory, a ZIP, or a JAR file. - * - * @param path the location path - * @return this operation instance - */ - public CompileOptions path(Path path) { - return path(path.toFile()); - } - - /** - * Place the generated class files into the specified location. - *

- * The location can be a directory, a ZIP, or a JAR file. - * - * @param path the location path - * @return this operation instance - */ - public CompileOptions path(String path) { - return path(new File(path)); - } - - /** - * Pass an option to a plugin. - * - * @param id the plugin ID - * @param optionName the plugin option name - * @param value the plugin option value - * @return this operation instance - */ - public CompileOptions plugin(String id, String optionName, String value) { - plugin_.add(id + ':' + optionName + ':' + value); - return this; - } - - /** - * Retrieves the plugin options. - * - * @return the plugin options. - */ - public Collection plugin() { - return plugin_; - } - - /** - * Allow using declarations only from the specified version of Kotlin bundled libraries. - * - * @param progressive {@code true} or {@code false} - * @return this operation instance - */ - public CompileOptions progressive(boolean progressive) { - progressive_ = progressive; - return this; - } - - /** - * Script definition template classes. - *

- * Use fully qualified class names. - * - * @param classNames one or more class names - * @return this operation instance - */ - public CompileOptions scriptTemplates(String... classNames) { - return scriptTemplates(List.of(classNames)); - } - - /** - * Retrieves the script templates. - * - * @return the script templates. - */ - public Collection scriptTemplates() { - return scriptTemplates_; - } - - /** - * Script definition template classes. - *

- * Use fully qualified class names. - * - * @param classNames the class names - * @return this operation instance - */ - public CompileOptions scriptTemplates(Collection classNames) { - scriptTemplates_.addAll(classNames); - return this; - } - - /** - * Enable verbose logging output which includes details of the compilation process. - * - * @param verbose {@code true} or {@code false} - * @return this operation instance - */ - public CompileOptions verbose(boolean verbose) { - verbose_ = verbose; - return this; - } - - /** - * Turn any warnings into a compilation error. - * - * @param wError {@code true} or {@code false} - * @return this operation instance - */ - public CompileOptions wError(boolean wError) { - wError_ = wError; - return this; - } - - /** - * Enable additional declaration, expression, and type compiler checks that emit warnings if {@code true}. - * - * @param wExtra {@code true} or {@code false} - * @return this operation instance - */ - public CompileOptions wExtra(boolean wExtra) { - wExtra_ = wExtra; - return this; - } -} diff --git a/src/main/java/rife/bld/extension/kotlin/CompilerPlugin.java b/src/main/java/rife/bld/extension/kotlin/CompilerPlugin.java deleted file mode 100644 index f1fd584..0000000 --- a/src/main/java/rife/bld/extension/kotlin/CompilerPlugin.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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.kotlin; - -/** - * @author Erik C. Thauvin - * Defines the known Kotlin compiler plugin JARs. - * - * @author Erik C. Thauvin - * @since 1.0 - */ -public enum CompilerPlugin { - ALL_OPEN("allopen-compiler-plugin.jar"), - ASSIGNMENT("assignment-compiler-plugin.jar"), - COMPOSE("compose-compiler-plugin.jar"), - KOTLIN_IMPORTS_DUMPER("kotlin-imports-dumper-compiler-plugin.jar"), - KOTLINX_SERIALIZATION("kotlinx-serialization-compiler-plugin.jar"), - KOTLIN_SERIALIZATION("kotlin-serialization-compiler-plugin.jar"), - LOMBOK("lombok-compiler-plugin.jar"), - NOARG("noarg-compiler-plugin.jar"), - POWER_ASSERT("power-assert-compiler-plugin.jar"), - SAM_WITH_RECEIVER("sam-with-receiver-compiler-plugin.jar"); - - public final String jar; - - CompilerPlugin(String jar) { - this.jar = jar; - } -} diff --git a/src/main/java/rife/bld/extension/kotlin/JvmOptions.java b/src/main/java/rife/bld/extension/kotlin/JvmOptions.java deleted file mode 100644 index 7e2ec62..0000000 --- a/src/main/java/rife/bld/extension/kotlin/JvmOptions.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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.kotlin; - -import rife.tools.StringUtils; - -import java.io.Serial; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * Java Virtual Machine options. - * - * @author Erik C. Thauvin - * @since 1.1.0 - */ -@SuppressWarnings("PMD.LooseCoupling") -public class JvmOptions extends ArrayList { - /** - * Keyword to enable native access for all code on the class path. - */ - public final static String ALL_UNNAMED = "ALL-UNNAMED"; - - @Serial - private static final long serialVersionUID = 1L; - - /** - * Modules that are permitted to perform restricted native operations. - * The module name can also be {@link #ALL_UNNAMED}. - * - * @param modules the module names - * @return this list of options - */ - public JvmOptions enableNativeAccess(String... modules) { - return enableNativeAccess(List.of(modules)); - } - - /** - * Modules that are permitted to perform restricted native operations. - * The module name can also be {@link #ALL_UNNAMED}. - * - * @param modules the module names - * @return this list of options - */ - public JvmOptions enableNativeAccess(Collection modules) { - add("--enable-native-access=" + StringUtils.join(modules, ",")); - return this; - } - - /** - * Controls what action the Java runtime takes when native access is not enabled for a module. - * - * @param access the access mode - * @return this list of options - */ - public JvmOptions illegalNativeAccess(NativeAccess access) { - add("--illegal-native-access=" + access.mode); - return this; - } - - /** - * Illegal native access modes. - */ - public enum NativeAccess { - ALLOW("allow"), - DENY("deny"), - WARN("warn"); - - public final String mode; - - NativeAccess(String mode) { - this.mode = mode; - } - } -} diff --git a/src/test/java/rife/bld/extension/CompileKotlinOperationTest.java b/src/test/java/rife/bld/extension/CompileKotlinOperationTest.java index 4e0182e..f64e6d3 100644 --- a/src/test/java/rife/bld/extension/CompileKotlinOperationTest.java +++ b/src/test/java/rife/bld/extension/CompileKotlinOperationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2023-2025 the original author or authors. + * Copyright 2023-2024 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,22 +16,17 @@ package rife.bld.extension; -import org.assertj.core.api.AutoCloseableSoftAssertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import rife.bld.BaseProject; import rife.bld.blueprints.BaseProjectBlueprint; -import rife.bld.extension.kotlin.CompileOptions; -import rife.bld.extension.kotlin.CompilerPlugin; -import rife.bld.extension.kotlin.JvmOptions; import rife.tools.FileUtils; import java.io.File; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; -import java.util.Locale; import java.util.Objects; import java.util.logging.ConsoleHandler; import java.util.logging.Level; @@ -39,11 +34,7 @@ import java.util.logging.Logger; import static org.assertj.core.api.Assertions.assertThat; -@SuppressWarnings("PMD.AvoidDuplicateLiterals") class CompileKotlinOperationTest { - private static final String FILE_1 = "file1"; - private static final String FILE_2 = "file2"; - @BeforeAll static void beforeAll() { var level = Level.ALL; @@ -56,98 +47,7 @@ class CompileKotlinOperationTest { } @Test - void testBuildMainDirectory() { - var foo = new File("foo"); - var bar = new File("bar"); - - var op = new CompileKotlinOperation().buildMainDirectory(foo); - assertThat(op.buildMainDirectory()).as("as file").isEqualTo(foo); - - op = op.buildMainDirectory(bar.toPath()); - assertThat(op.buildMainDirectory()).as("as path").isEqualTo(bar); - - op = new CompileKotlinOperation().buildMainDirectory("foo"); - assertThat(op.buildMainDirectory()).as("as string").isEqualTo(foo); - } - - @Test - void testBuildTestDirectory() { - var foo = new File("foo"); - var bar = new File("bar"); - - var op = new CompileKotlinOperation().buildTestDirectory(foo); - assertThat(op.buildTestDirectory()).as("as file").isEqualTo(foo); - - op = op.buildTestDirectory(bar.toPath()); - assertThat(op.buildTestDirectory()).as("as path").isEqualTo(bar); - - op = new CompileKotlinOperation().buildTestDirectory("foo"); - assertThat(op.buildTestDirectory()).as("as string").isEqualTo(foo); - } - - @Test - void testCollections() { - var op = new CompileKotlinOperation() - .fromProject(new BaseProjectBlueprint(new File("examples"), "com.example", "Example", "Example")) - .kotlinHome("/kotlin_home") - .kotlinc("kotlinc") - .workDir("work_dir") - .compileMainClasspath("path1", "path2") - .compileOptions(new CompileOptions().jdkRelease("17").verbose(true)) - .mainSourceDirectories("dir1", "dir2") - .mainSourceDirectories(List.of(new File("dir3"), new File("dir4"))) - .mainSourceFiles("file1", "file2") - .mainSourceFiles(List.of(new File("file3"), new File("file4"))) - .mainSourceFiles(new File("file5"), new File("file6")) - .testSourceDirectories("tdir1", "tdir2") - .testSourceDirectories(List.of(new File("tdir3"), new File("tdir4"))) - .testSourceFiles("tfile1", "tfile2") - .testSourceFiles(List.of(new File("tfile3"), new File("tfile4"))) - .testSourceFiles(new File("tfile5"), new File("tfile6")) - .plugins("plugin1", "plugin2") - .plugins(CompilerPlugin.KOTLIN_SERIALIZATION, CompilerPlugin.ASSIGNMENT, CompilerPlugin.COMPOSE) - .plugins(new File("lib/compile"), CompilerPlugin.LOMBOK, CompilerPlugin.POWER_ASSERT) - .plugins(Path.of("lib/compile"), CompilerPlugin.NOARG, CompilerPlugin.ALL_OPEN, - CompilerPlugin.KOTLIN_IMPORTS_DUMPER) - .plugins("lib/compile", CompilerPlugin.KOTLINX_SERIALIZATION, CompilerPlugin.SAM_WITH_RECEIVER) - .plugins(List.of("plugin3", "plugin4")); - - try (var softly = new AutoCloseableSoftAssertions()) { - softly.assertThat(op.kotlinHome().getName()).as("kotlin_home").isEqualTo("kotlin_home"); - softly.assertThat(op.kotlinc().getName()).as("kotlinc").isEqualTo("kotlinc"); - softly.assertThat(op.workDir().getName()).as("work_dir").isEqualTo("work_dir"); - softly.assertThat(op.compileMainClasspath()).as("compileMainClassPath") - .containsAll(List.of("path1", "path2")); - softly.assertThat(op.compileOptions().hasRelease()).as("hasRelease").isTrue(); - softly.assertThat(op.compileOptions().isVerbose()).as("isVerbose").isTrue(); - softly.assertThat(op.mainSourceDirectories()).as("mainSourceDirectories").containsExactly( - Path.of("examples", "src", "main", "kotlin").toFile(), new File("dir1"), - new File("dir2"), new File("dir3"), new File("dir4")); - softly.assertThat(op.testSourceDirectories()).as("testSourceDirectories").containsOnly( - Path.of("examples", "src", "test", "kotlin").toFile(), new File("tdir1"), - new File("tdir2"), new File("tdir3"), new File("tdir4")); - softly.assertThat(op.mainSourceFiles()).as("mainSourceFiles").containsOnly( - new File("file1"), new File("file2"), new File("file3"), - new File("file4"), new File("file5"), new File("file6")); - softly.assertThat(op.testSourceFiles()).as("testSourceFiles").containsOnly( - new File("tfile1"), new File("tfile2"), new File("tfile3"), - new File("tfile4"), new File("tfile5"), new File("tfile6")); - softly.assertThat(op.plugins()).as("plugins").contains("plugin1", "plugin2", "plugin3", "plugin4", - new File("/kotlin_home/lib/kotlin-serialization-compiler-plugin.jar").getAbsolutePath(), - new File("/kotlin_home/lib/assignment-compiler-plugin.jar").getAbsolutePath(), - new File("/kotlin_home/lib/compose-compiler-plugin.jar").getAbsolutePath(), - new File("lib/compile", "lombok-compiler-plugin.jar").getAbsolutePath(), - new File("lib/compile", "power-assert-compiler-plugin.jar").getAbsolutePath(), - new File("lib/compile", "noarg-compiler-plugin.jar").getAbsolutePath(), - new File("lib/compile", "allopen-compiler-plugin.jar").getAbsolutePath(), - new File("lib/compile", "kotlin-imports-dumper-compiler-plugin.jar").getAbsolutePath(), - new File("lib/compile", "kotlinx-serialization-compiler-plugin.jar").getAbsolutePath(), - new File("lib/compile", "sam-with-receiver-compiler-plugin.jar").getAbsolutePath()); - } - } - - @Test - void testExecute() throws Exception { + void testExecute() throws IOException { var tmpDir = Files.createTempDirectory("bld-kotlin").toFile(); try { @@ -155,10 +55,8 @@ class CompileKotlinOperationTest { var mainDir = new File(buildDir, "main"); var testDir = new File(buildDir, "test"); - try (var softly = new AutoCloseableSoftAssertions()) { - softly.assertThat(mainDir.mkdirs()).as("make mainDir").isTrue(); - softly.assertThat(testDir.mkdirs()).as("make testDir").isTrue(); - } + assertThat(mainDir.mkdirs()).isTrue(); + assertThat(testDir.mkdirs()).isTrue(); var compileJars = new ArrayList(); for (var f : Objects.requireNonNull(new File("examples/lib/compile").listFiles())) { @@ -171,7 +69,8 @@ class CompileKotlinOperationTest { } var op = new CompileKotlinOperation() - .fromProject(new BaseProjectBlueprint(new File("examples"), "com.example", "Example", "Example")) + .fromProject(new BaseProjectBlueprint(new File("examples"), "com.example", + "Example")) .buildMainDirectory(mainDir) .buildTestDirectory(testDir) .compileMainClasspath(compileJars) @@ -180,268 +79,26 @@ class CompileKotlinOperationTest { .compileTestClasspath(mainDir.getAbsolutePath()); op.compileOptions().verbose(true); - op.compileOptions().argFile("src/test/resources/argfile.txt", "src/test/resources/argfile2.txt"); - - if (!CompileKotlinOperation.isWindows()) { - op.jvmOptions().enableNativeAccess(JvmOptions.ALL_UNNAMED); - assertThat(op.jvmOptions()).containsExactly("--enable-native-access=ALL-UNNAMED"); - } + op.compileOptions().jdkRelease("17"); var args = op.compileOptions().args(); - var matches = List.of("-Xjdk-release=17", "-no-reflect", "-progressive", "-include-runtime", "-no-stdlib", - "-verbose"); - assertThat(args).as(args + " == " + matches).isEqualTo(matches); + var matches = List.of("-Xjdk-release=17", "-no-stdlib", "-verbose"); + assertThat(args).isEqualTo(matches); op.execute(); - try (var softly = new AutoCloseableSoftAssertions()) { - softly.assertThat(tmpDir).as("tmpDir").isNotEmptyDirectory(); - softly.assertThat(mainDir).as("mainDir").isNotEmptyDirectory(); - softly.assertThat(testDir).as("testDir").isNotEmptyDirectory(); - } + assertThat(tmpDir).isNotEmptyDirectory(); + assertThat(mainDir).isNotEmptyDirectory(); + assertThat(testDir).isNotEmptyDirectory(); var mainOut = Path.of(mainDir.getAbsolutePath(), "com", "example").toFile(); - try (var softly = new AutoCloseableSoftAssertions()) { - softly.assertThat(new File(mainOut, "Example.class")).as("Example.class").exists(); - softly.assertThat(new File(mainOut, "Example$Companion.class")) - .as("ExampleCompanion.class").exists(); - } + assertThat(new File(mainOut, "Example.class")).exists(); + assertThat(new File(mainOut, "Example$Companion.class")).exists(); var testOut = Path.of(testDir.getAbsolutePath(), "com", "example").toFile(); - assertThat(new File(testOut, "ExampleTest.class")).as("ExampleTest.class").exists(); + assertThat(new File(testOut, "ExampleTest.class")).exists(); } finally { FileUtils.deleteDirectory(tmpDir); } } - - @Test - void testFindKotlincPath() { - assertThat(CompileKotlinOperation.findKotlincPath()).doesNotStartWith("kotlinc"); - } - - @Test - void testFromProject() { - var examples = new File("examples"); - var op = new CompileKotlinOperation().fromProject( - new BaseProjectBlueprint(examples, "com.example", "examples", "examples")); - assertThat(op.mainSourceDirectories()).containsExactly(new File(examples, "src/main/kotlin")); - assertThat(op.testSourceDirectories()).containsExactly(new File(examples, "src/test/kotlin")); - } - - @Test - void testFromProjectNoKotlin() { - var op = new CompileKotlinOperation().fromProject( - new BaseProjectBlueprint(new File("foo"), "org.example", "foo", "foo")); - assertThat(op.mainSourceDirectories()).isEmpty(); - assertThat(op.testSourceDirectories()).isEmpty(); - } - - @Test - void testIsOS() { - var osName = System.getProperty("os.name"); - if (osName != null) { - var os = osName.toLowerCase(Locale.US); - if (os.contains("win")) { - assertThat(CompileKotlinOperation.isWindows()).isTrue(); - } else if (os.contains("linux") || os.contains("unix")) { - assertThat(CompileKotlinOperation.isLinux()).isTrue(); - } else if (os.contains("mac") || os.contains("darwin")) { - assertThat(CompileKotlinOperation.isMacOS()).isTrue(); - } - } - } - - @Test - void testKotlinHome() { - var foo = new File("foo"); - var bar = new File("bar"); - - var op = new CompileKotlinOperation().kotlinHome(foo); - assertThat(op.kotlinHome()).as("as file").isEqualTo(foo); - - op = op.kotlinHome(bar.toPath()); - assertThat(op.kotlinHome()).as("as path").isEqualTo(bar); - - op = new CompileKotlinOperation().kotlinHome("foo"); - assertThat(op.kotlinHome()).as("as string").isEqualTo(foo); - } - - @Test - void testKotlinc() { - var foo = new File("foo"); - var bar = new File("bar"); - - var op = new CompileKotlinOperation().kotlinc(foo); - assertThat(op.kotlinc()).as("as file").isEqualTo(foo); - - op = op.kotlinc(bar.toPath()); - assertThat(op.kotlinc()).as("as path").isEqualTo(bar); - - op = new CompileKotlinOperation().kotlinc("foo"); - assertThat(op.kotlinc()).as("as string").isEqualTo(foo); - } - - @Test - void testMainSourceDirectories() { - var op = new CompileKotlinOperation(); - - op.mainSourceDirectories(List.of(new File(FILE_1), new File(FILE_2))); - assertThat(op.mainSourceDirectories()).as("List(File...)").containsExactly(new File(FILE_1), new File(FILE_2)); - op.mainSourceDirectories().clear(); - - op.mainSourceDirectories(new File(FILE_1), new File(FILE_2)); - assertThat(op.mainSourceDirectories()).as("File...").containsExactly(new File(FILE_1), new File(FILE_2)); - op.mainSourceDirectories().clear(); - - op.mainSourceDirectories(FILE_1, FILE_2); - assertThat(op.mainSourceDirectories()).as("String...") - .containsExactly(new File(FILE_1), new File(FILE_2)); - op.mainSourceDirectories().clear(); - - op = op.mainSourceDirectories(Path.of(FILE_1), Path.of(FILE_2)); - assertThat(op.mainSourceDirectories()).as("Path...") - .containsExactly(new File(FILE_1), new File(FILE_2)); - op.mainSourceDirectories().clear(); - - op.mainSourceDirectoriesPaths(List.of(new File(FILE_1).toPath(), new File(FILE_2).toPath())); - assertThat(op.mainSourceDirectories()).as("List(Path...)") - .containsExactly(new File(FILE_1), new File(FILE_2)); - op.mainSourceDirectories().clear(); - - op.mainSourceDirectoriesStrings(List.of(FILE_1, FILE_2)); - assertThat(op.mainSourceDirectories()).as("List(String...)") - .containsExactly(new File(FILE_1), new File(FILE_2)); - op.mainSourceDirectories().clear(); - } - - @Test - void testMainSourceFiles() { - var op = new CompileKotlinOperation(); - - op.mainSourceFiles(List.of(new File(FILE_1), new File(FILE_2))); - assertThat(op.mainSourceFiles()).as("List(File...)").containsExactly(new File(FILE_1), new File(FILE_2)); - op.mainSourceFiles().clear(); - - op.mainSourceFiles(new File(FILE_1), new File(FILE_2)); - assertThat(op.mainSourceFiles()).as("File...").containsExactly(new File(FILE_1), new File(FILE_2)); - op.mainSourceFiles().clear(); - - op.mainSourceFiles(FILE_1, FILE_2); - assertThat(op.mainSourceFiles()).as("String...") - .containsExactly(new File(FILE_1), new File(FILE_2)); - op.mainSourceFiles().clear(); - - op = op.mainSourceFiles(Path.of(FILE_1), Path.of(FILE_2)); - assertThat(op.mainSourceFiles()).as("Path...") - .containsExactly(new File(FILE_1), new File(FILE_2)); - op.mainSourceFiles().clear(); - - op.mainSourceFilesPaths(List.of(new File(FILE_1).toPath(), new File(FILE_2).toPath())); - assertThat(op.mainSourceFiles()).as("List(Path...)").containsExactly(new File(FILE_1), new File(FILE_2)); - op.mainSourceFiles().clear(); - - op.mainSourceFilesStrings(List.of(FILE_1, FILE_2)); - assertThat(op.mainSourceFiles()).as("List(String...)").containsExactly(new File(FILE_1), new File(FILE_2)); - op.mainSourceFiles().clear(); - } - - @Test - @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops") - void testPlugins() { - var op = new CompileKotlinOperation() - .fromProject(new BaseProject()) - .plugins(CompilerPlugin.ALL_OPEN, - CompilerPlugin.ASSIGNMENT, - CompilerPlugin.COMPOSE, - CompilerPlugin.KOTLIN_IMPORTS_DUMPER, - CompilerPlugin.KOTLINX_SERIALIZATION, - CompilerPlugin.KOTLIN_SERIALIZATION, - CompilerPlugin.LOMBOK, - CompilerPlugin.NOARG, - CompilerPlugin.POWER_ASSERT, - CompilerPlugin.SAM_WITH_RECEIVER); - - try (var softly = new AutoCloseableSoftAssertions()) { - for (var p : op.plugins()) { - softly.assertThat(new File(p)).as(p).exists(); - } - } - } - - @Test - void testTestSourceDirectories() { - var op = new CompileKotlinOperation(); - - op.testSourceDirectories(List.of(new File(FILE_1), new File(FILE_2))); - assertThat(op.testSourceDirectories()).as("List(File...)").containsExactly(new File(FILE_1), new File(FILE_2)); - op.testSourceDirectories().clear(); - - op.testSourceDirectories(new File(FILE_1), new File(FILE_2)); - assertThat(op.testSourceDirectories()).as("File...").containsExactly(new File(FILE_1), new File(FILE_2)); - op.testSourceDirectories().clear(); - - op.testSourceDirectories(FILE_1, FILE_2); - assertThat(op.testSourceDirectories()).as("String...") - .containsExactly(new File(FILE_1), new File(FILE_2)); - op.testSourceDirectories().clear(); - - op = op.testSourceDirectories(Path.of(FILE_1), Path.of(FILE_2)); - assertThat(op.testSourceDirectories()).as("Path...") - .containsExactly(new File(FILE_1), new File(FILE_2)); - op.testSourceDirectories().clear(); - - op.testSourceDirectoriesPaths(List.of(new File(FILE_1).toPath(), new File(FILE_2).toPath())); - assertThat(op.testSourceDirectories()).as("List(Path...)").containsExactly(new File(FILE_1), new File(FILE_2)); - op.testSourceDirectories().clear(); - - op.testSourceDirectoriesStrings(List.of(FILE_1, FILE_2)); - assertThat(op.testSourceDirectories()).as("List(String...)").containsExactly(new File(FILE_1), new File(FILE_2)); - op.testSourceDirectories().clear(); - } - - @Test - void testTestSourceFiles() { - var op = new CompileKotlinOperation(); - - op.testSourceFiles(List.of(new File(FILE_1), new File(FILE_2))); - assertThat(op.testSourceFiles()).as("List(File...)").containsExactly(new File(FILE_1), new File(FILE_2)); - op.testSourceFiles().clear(); - - op.testSourceFiles(new File(FILE_1), new File(FILE_2)); - assertThat(op.testSourceFiles()).as("File...").containsExactly(new File(FILE_1), new File(FILE_2)); - op.testSourceFiles().clear(); - - op.testSourceFiles(FILE_1, FILE_2); - assertThat(op.testSourceFiles()).as("String...") - .containsExactly(new File(FILE_1), new File(FILE_2)); - op.testSourceFiles().clear(); - - op = op.testSourceFiles(Path.of(FILE_1), Path.of(FILE_2)); - assertThat(op.testSourceFiles()).as("Path...") - .containsExactly(new File(FILE_1), new File(FILE_2)); - op.testSourceFiles().clear(); - - op.testSourceFilesPaths(List.of(new File(FILE_1).toPath(), new File(FILE_2).toPath())); - assertThat(op.testSourceFiles()).as("List(Path...)").containsExactly(new File(FILE_1), new File(FILE_2)); - op.testSourceFiles().clear(); - - op.testSourceFilesStrings(List.of(FILE_1, FILE_2)); - assertThat(op.testSourceFiles()).as("List(String...)").containsExactly(new File(FILE_1), new File(FILE_2)); - op.testSourceFiles().clear(); - } - - @Test - void testWorkDir() { - var foo = new File("foo"); - var bar = new File("bar"); - - var op = new CompileKotlinOperation().workDir(foo); - assertThat(op.workDir()).as("as file").isEqualTo(foo); - - op = op.workDir(bar.toPath()); - assertThat(op.workDir()).as("as path").isEqualTo(bar); - - op = new CompileKotlinOperation().workDir("foo"); - assertThat(op.workDir()).as("as string").isEqualTo(foo); - } } diff --git a/src/test/java/rife/bld/extension/CompileKotlinOptionsTest.java b/src/test/java/rife/bld/extension/CompileKotlinOptionsTest.java new file mode 100644 index 0000000..f19663d --- /dev/null +++ b/src/test/java/rife/bld/extension/CompileKotlinOptionsTest.java @@ -0,0 +1,112 @@ +/* + * Copyright 2023-2024 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.Test; + +import java.io.File; +import java.util.List; +import java.util.stream.IntStream; + +import static org.assertj.core.api.Assertions.assertThat; + +@SuppressWarnings("PMD.AvoidDuplicateLiterals") +class CompileKotlinOptionsTest { + @Test + void argsCollectionTest() { + var args = new CompileKotlinOptions() + .argFile(List.of("arg1.txt", "arg2.txt")) + .classpath(List.of("path1", "path2")) + .noStdLib(false) + .optIn(List.of("opt1", "opt2")) + .options(List.of("-foo", "-bar")) + .scriptTemplates(List.of("temp1", "temp2")) + .args(); + var matches = List.of( + "@arg1.txt", "@arg2.txt", + "-classpath", "path1:path2", + "-opt-in", "opt1", + "-opt-in", "opt2", + "-foo", + "-bar", + "-script-templates", "temp1,temp2"); + + assertThat(args).hasSize(matches.size()); + + IntStream.range(0, args.size()).forEach(i -> assertThat(args.get(i)).isEqualTo(matches.get(i))); + + + } + + @Test + void argsTest() { + var args = new CompileKotlinOptions() + .apiVersion("11") + .argFile("file.txt", "file2.txt") + .classpath("path1", "path2") + .javaParameters(true) + .jvmTarget("11") + .includeRuntime(true) + .jdkHome("path") + .jdkRelease("11") + .kotlinHome("path") + .languageVersion("1.0") + .moduleName("module") + .noJdk(true) + .noReflect(true) + .noWarn(true) + .optIn("opt1", "opt2") + .options("-foo", "-bar") + .path("path") + .plugin("id", "name", "value") + .progressive(true) + .scriptTemplates("name", "name2") + .verbose(true) + .wError(true) + .args(); + + var matches = List.of( + "-api-version", "11", + "@file.txt", "@file2.txt", + "-classpath", "path1" + File.pathSeparator + "path2", + "-java-parameters", + "-jvm-target", "11", + "-include-runtime", + "-jdk-home", "path", + "-Xjdk-release=11", + "-kotlin-home", "path", + "-language-version", "1.0", + "-module-name", "module", + "-no-jdk", + "-no-reflect", + "-no-warn", + "-opt-in", "opt1", + "-opt-in", "opt2", + "-foo", + "-bar", + "-d", "path", + "-P", "plugin:id:name:value", + "-progressive", + "-script-templates", "name,name2", + "-verbose", + "-Werror"); + + assertThat(args).hasSize(matches.size()); + + IntStream.range(0, args.size()).forEach(i -> assertThat(args.get(i)).isEqualTo(matches.get(i))); + } +} diff --git a/src/test/java/rife/bld/extension/dokka/DokkaOperationTest.java b/src/test/java/rife/bld/extension/dokka/DokkaOperationTest.java new file mode 100644 index 0000000..637b1f2 --- /dev/null +++ b/src/test/java/rife/bld/extension/dokka/DokkaOperationTest.java @@ -0,0 +1,95 @@ +/* + * Copyright 2023-2024 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.dokka; + +import org.junit.jupiter.api.Test; +import rife.bld.blueprints.BaseProjectBlueprint; + +import java.io.File; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.IntStream; + +import static org.assertj.core.api.Assertions.assertThat; + +class DokkaOperationTest { + @Test + @SuppressWarnings({"ExtractMethodRecommender", "PMD.AvoidDuplicateLiterals"}) + void executeConstructProcessCommandListTest() { + var examples = new File("examples"); + var args = new DokkaOperation() + .fromProject(new BaseProjectBlueprint(examples, "com.example", "Example")) + .globalLinks("s", "link") + .globalLinks(Map.of("s2", "link2")) + .globalPackageOptions("option1", "option2") + .globalPackageOptions(List.of("option3", "option4")) + .globalSrcLink("link1", "link2") + .globalSrcLink(List.of("link3", "link4")) + .includes("file1", "file2") + .pluginConfiguration("name", "\"json\"") + .pluginConfiguration(Map.of("\"name2\"", "json2")) + .pluginsClasspath("path1", "path2") + .pluginsClasspath(List.of("path3", "path4")) + .delayTemplateSubstitution(true) + .failOnWarning(true) + .loggingLevel(LoggingLevel.DEBUG) + .moduleName("name") + .moduleVersion("1.0") + .noSuppressObviousFunctions(true) + .offlineMode(true) + .outputDir(new File(examples, "build")) + .outputFormat(OutputFormat.JAVADOC) + .suppressInheritedMembers(true) + .executeConstructProcessCommandList(); + + var path = examples.getAbsolutePath(); + var matches = List.of("java", + "-jar", path + "/lib/bld/dokka-cli-1.9.10.jar", + "-pluginsClasspath", path + "/lib/bld/dokka-base-1.9.10.jar;" + + path + "/lib/bld/analysis-kotlin-descriptors-1.9.10.jar;" + + path + "/lib/bld/javadoc-plugin-1.9.10.jar;" + + path + "/lib/bld/korte-jvm-2.7.0.jar;" + + path + "/lib/bld/kotlin-as-java-plugin-1.9.10.jar;path1;path2;path3;path4", + "-sourceSet", "-src " + path + "/src/main/kotlin", + "-outputDir", path + "/build", + "-delayTemplateSubstitution", "true", + "-failOnWarning", "true", + "-globalLinks", "s^link^^s2^link2", + "-globalPackageOptions", "option1;option2;option3;option4", + "-globalSrcLinks_", "link1;link2;link3;link4", + "-includes", "file1;file2", + "-loggingLevel", "debug", + "-moduleName", "name", + "-moduleVersion", "1.0", + "-noSuppressObviousFunctions", "true", + "-offlineMode", "true", + "-pluginConfiguration", "{name}={\\\"json\\\"}^^{\\\"name2\\\"}={json2}", + "-suppressInheritedMembers", "true"); + + assertThat(args).hasSize(matches.size()); + + IntStream.range(0, args.size()).forEach(i -> { + if (args.get(i).contains(".jar;")) { + var jars = args.get(i).split(";"); + Arrays.stream(jars).forEach(jar -> assertThat(matches.get(i)).contains(jar)); + } else { + assertThat(args.get(i)).isEqualTo(matches.get(i)); + } + }); + } +} diff --git a/src/test/java/rife/bld/extension/dokka/SourceSetTest.java b/src/test/java/rife/bld/extension/dokka/SourceSetTest.java new file mode 100644 index 0000000..4edefe0 --- /dev/null +++ b/src/test/java/rife/bld/extension/dokka/SourceSetTest.java @@ -0,0 +1,109 @@ +/* + * Copyright 2023-2024 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.dokka; + +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Map; +import java.util.stream.IntStream; + +import static org.assertj.core.api.Assertions.assertThat; + +class SourceSetTest { + @Test + void sourceSetCollectionsTest() { + var args = new SourceSet() + .classpath(List.of("path1", "path2")) + .dependentSourceSets(Map.of("set1", "set2", "set3", "set4")) + .externalDocumentationLinks(Map.of("link1", "link2", "link3", "link4")) + .perPackageOptions(List.of("option1", "option2")) + .samples(List.of("samples1", "samples1")) + .suppressedFiles(List.of("sup1", "sup2")) + .args(); + + var matches = List.of( + "-classpath", "path1;path2", + "-dependentSourceSets", "set1/set2;set3/set4", + "-externalDocumentationLinks", "link3^link4^^link1^link2", + "-perPackageOptions", "option1;option2", + "-samples", "samples1;samples1", + "-suppressedFiles", "sup1;sup2" + ); + + assertThat(args).hasSize(matches.size()); + + IntStream.range(0, args.size()).forEach(i -> assertThat(args.get(i)).isEqualTo(matches.get(i))); + } + + @Test + @SuppressWarnings("PMD.AvoidDuplicateLiterals") + void sourceSetTest() { + var args = new SourceSet() + .classpath("classpath1", "classpath2") + .dependentSourceSets("moduleName", "sourceSetName") + .documentedVisibilities(DocumentedVisibility.PACKAGE, DocumentedVisibility.PRIVATE) + .externalDocumentationLinks("url1", "packageListUrl1") + .externalDocumentationLinks("url2", "packageListUrl2") + .includes("includes1", "includes2") + .perPackageOptions("options1", "options2") + .samples("samples1", "sample2") + .srcLink("path1", "remote1", "#suffix1") + .srcLink("path2", "remote2", "#suffix2") + .src("src1", "src2") + .suppressedFiles("sup1", "sup2") + .analysisPlatform(AnalysisPlatform.JVM) + .apiVersion("1.0") + .displayName("name") + .jdkVersion(18) + .languageVersion("2.0") + .noJdkLink(true) + .noSkipEmptyPackages(true) + .noStdlibLink(true) + .reportUndocumented(true) + .skipDeprecated(true) + .sourceSetName("setName") + .args(); + + var matches = List.of( + "-analysisPlatform", "jvm", + "-apiVersion", "1.0", + "-classpath", "classpath1;classpath2", + "-dependentSourceSets", "moduleName/sourceSetName", + "-displayName", "name", + "-documentedVisibilities", "package;private", + "-externalDocumentationLinks", "url1^packageListUrl1^^url2^packageListUrl2", + "-jdkVersion", "18", + "-includes", "includes1;includes2", + "-languageVersion", "2.0", + "-noJdkLink", "true", + "-noSkipEmptyPackages", "true", + "-noStdlibLink", "true", + "-reportUndocumented", "true", + "-perPackageOptions", "options1;options2", + "-samples", "samples1;sample2", + "-skipDeprecated", "true", + "-src", "src1;src2", + "-srcLink", "path1=remote1#suffix1;path2=remote2#suffix2", + "-sourceSetName", "setName", + "-suppressedFiles", "sup1;sup2"); + + assertThat(args).hasSize(matches.size()); + + IntStream.range(0, args.size()).forEach(i -> assertThat(args.get(i)).isEqualTo(matches.get(i))); + } +} diff --git a/src/test/java/rife/bld/extension/kotlin/CompileOptionsTest.java b/src/test/java/rife/bld/extension/kotlin/CompileOptionsTest.java deleted file mode 100644 index c6e6965..0000000 --- a/src/test/java/rife/bld/extension/kotlin/CompileOptionsTest.java +++ /dev/null @@ -1,393 +0,0 @@ -/* - * 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.kotlin; - -import org.assertj.core.api.AutoCloseableSoftAssertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.EnabledOnOs; -import org.junit.jupiter.api.condition.OS; - -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.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import static org.assertj.core.api.Assertions.assertThat; - -@SuppressWarnings("PMD.AvoidDuplicateLiterals") -class CompileOptionsTest { - /** - * Returns the local path of the given file names. - * - * @param fileNames The file names - * @return the local path - */ - private String localPath(String... fileNames) { - return Arrays.stream(fileNames).map(it -> new File(it).getAbsolutePath()) - .collect(Collectors.joining(File.pathSeparator)); - } - - @Test - @SuppressWarnings("PMD.UnitTestShouldIncludeAssert") - void testArgs() { - var options = new CompileOptions() - .apiVersion("11") - .javaParameters(true) - .jvmTarget("11") - .includeRuntime(true) - .jdkHome(new File("path")) - .jdkRelease("11") - .kotlinHome(new File("path")) - .languageVersion("1.0") - .moduleName("module") - .noJdk(true) - .noReflect(true) - .noWarn(true) - .optIn("opt1", "opt2") - .options("-foo", "-bar") - .path("path") - .plugin("id", "name", "value") - .progressive(true) - .scriptTemplates("name", "name2") - .verbose(true) - .wError(true) - .wExtra(true); - - var matches = List.of( - "-api-version", "11", - "-java-parameters", - "-jvm-target", "11", - "-include-runtime", - "-jdk-home", localPath("path"), - "-Xjdk-release=11", - "-kotlin-home", localPath("path"), - "-language-version", "1.0", - "-module-name", "module", - "-no-jdk", - "-no-reflect", - "-nowarn", - "-opt-in", "opt1", - "-opt-in", "opt2", - "-foo", - "-bar", - "-d", localPath("path"), - "-P", "plugin:id:name:value", - "-progressive", - "-script-templates", "name,name2", - "-verbose", - "-Werror", - "-Wextra"); - - var args = new ArrayList>(); - args.add(options.args()); - args.add(options.apiVersion(11).jvmTarget(11).args()); - - try (var softly = new AutoCloseableSoftAssertions()) { - for (var a : args) { - IntStream.range(0, a.size()).forEach(i -> softly.assertThat(a.get(i)) - .as(a.get(i) + " == " + matches.get(i)).isEqualTo(matches.get(i))); - } - } - } - - @Test - void testArgsCollections() { - var advanceOptions = List.of("-Xoption1", "option=2"); - var argFile = List.of(new File("arg1.txt"), new File("arg2.txt")); - var classpath = List.of(new File("path1"), new File("path2")); - var optIn = List.of("opt1", "opt2"); - var options = List.of("-foo", "-bar"); - var plugin = List.of("id:name:value", "id2:name2:value2"); - var scriptTemplates = List.of("temp1", "temp2"); - - var op = new CompileOptions() - .advancedOptions(advanceOptions) - .argFile(argFile) - .classpath(classpath) - .noStdLib(false) - .optIn(optIn) - .options(options) - .scriptTemplates(scriptTemplates); - - plugin.forEach(it -> { - var p = it.split(":"); - op.plugin(p[0], p[1], p[2]); - }); - - try (var softly = new AutoCloseableSoftAssertions()) { - softly.assertThat(op.advancedOptions()).as("advancedOptions") - .hasSize(advanceOptions.size()).containsAll(advanceOptions); - softly.assertThat(op.argFile()).as("argFile") - .hasSize(argFile.size()).containsAll(argFile); - softly.assertThat(op.classpath()).as("classpath") - .hasSize(classpath.size()).containsAll(classpath); - softly.assertThat(op.optIn()).as("optIn") - .hasSize(optIn.size()).containsAll(optIn); - softly.assertThat(op.options()).as("options") - .hasSize(options.size()).containsAll(options); - softly.assertThat(op.plugin()).as("plugin") - .hasSize(plugin.size()).containsAll(plugin); - softly.assertThat(op.scriptTemplates()).as("scriptTemplates") - .hasSize(scriptTemplates.size()).containsAll(scriptTemplates); - } - - var matches = List.of( - '@' + localPath("arg1.txt"), '@' + localPath("arg2.txt"), - "-classpath", localPath("path1", "path2"), - "-Joption1", "-Joption2", - "-opt-in", "opt1", - "-opt-in", "opt2", - "-foo", "-bar", - "-script-templates", - "temp1,temp2", - "-Xoption1", "-Xoption=2", - "-P", "plugin:id:name:value", - "-P", "plugin:id2:name2:value2"); - - try (var softly = new AutoCloseableSoftAssertions()) { - var args = op.args(); - for (var arg : args) { - var found = false; - for (var match : matches) { - if (match.equals(arg)) { - found = true; - break; - } - } - softly.assertThat(found).as(arg + " not found.").isTrue(); - } - } - } - - @Test - void testArgsFile() { - var foo = new File("foo.txt"); - var bar = new File("bar.txt"); - var options = new CompileOptions(); - - options = options.argFile(foo); - assertThat(options.argFile()).contains(foo); - options.argFile().clear(); - assertThat(options.argFile()).isEmpty(); - - options.argFile(foo, bar); - assertThat(options.argFile()).contains(foo, bar); - options.argFile().clear(); - assertThat(options.argFile()).isEmpty(); - - options = options.argFile(foo.toPath(), bar.toPath()); - assertThat(options.argFile()).contains(foo, bar); - options.argFile().clear(); - assertThat(options.argFile()).isEmpty(); - - options = options.argFile(foo.getAbsolutePath(), bar.getAbsolutePath()); - assertThat(options.argFile()).contains(new File(foo.getAbsolutePath()), new File(bar.getAbsolutePath())); - } - - @Test - @EnabledOnOs(OS.LINUX) - void testCheckAllParams() throws IOException { - var args = Files.readAllLines(Paths.get("src", "test", "resources", "kotlinc-args.txt")); - - assertThat(args).isNotEmpty(); - - var params = new CompileOptions() - .advancedOptions("Xoption") - .apiVersion("11") - .expression("expression") - .includeRuntime(true) - .javaParameters(true) - .jdkHome("jdkhome") - .jvmTarget(12) - .kotlinHome("kotlin") - .languageVersion("1.0") - .moduleName("moduleName") - .noJdk(true) - .noReflect(true) - .noStdLib(true) - .noWarn(true) - .optIn("annotation") - .options("option") - .path(new File("path")) - .plugin("id", "option", "value") - .progressive(true) - .scriptTemplates("template") - .verbose(true) - .wError(true) - .wExtra(true); - - var skipArgs = List.of("-J", "-classpath", "@"); - assertThat(args).as(skipArgs + " not found.").containsAll(skipArgs); - args.removeAll(skipArgs); - - try (var softly = new AutoCloseableSoftAssertions()) { - for (var p : args) { - var found = false; - for (var a : params.args()) { - if (a.startsWith(p)) { - found = true; - break; - } - } - softly.assertThat(found).as(p + " not found.").isTrue(); - } - } - } - - @Test - void testClasspath() { - var foo = new File("foo.txt"); - var bar = new File("bar.txt"); - var options = new CompileOptions(); - - options = options.classpath(foo); - assertThat(options.classpath()).as("File").containsExactly(foo); - options.classpath().clear(); - assertThat(options.argFile()).isEmpty(); - - - options.classpath(foo, bar); - assertThat(options.classpath()).as("File...").containsExactly(foo, bar); - options.classpath().clear(); - assertThat(options.argFile()).isEmpty(); - - - options.classpath(List.of(foo, bar)); - assertThat(options.classpath()).as("List(File...)").containsExactly(foo, bar); - options.classpath().clear(); - assertThat(options.argFile()).isEmpty(); - - - options = options.classpath(foo.toPath(), bar.toPath()); - assertThat(options.classpath()).as("Path...").containsExactly(foo, bar); - options.classpath().clear(); - assertThat(options.argFile()).isEmpty(); - - - options = options.classpathPaths(List.of(foo.toPath(), bar.toPath())); - assertThat(options.classpath()).as("List(Path...)").containsExactly(foo, bar); - options.classpath().clear(); - assertThat(options.argFile()).isEmpty(); - - - options.classpath(foo.getAbsolutePath(), bar.getAbsolutePath()); - assertThat(options.classpath()).as("String...") - .containsExactly(new File(foo.getAbsolutePath()), new File(bar.getAbsolutePath())); - options.classpath().clear(); - assertThat(options.argFile()).isEmpty(); - - options.classpathStrings(List.of(foo.getAbsolutePath(), bar.getAbsolutePath())); - assertThat(options.classpath()).as("List(String...)") - .containsExactly(new File(foo.getAbsolutePath()), new File(bar.getAbsolutePath())); - } - - @Test - void testJdkHome() { - var foo = new File("foo.txt"); - var options = new CompileOptions(); - - options.jdkHome(foo); - assertThat(options.jdkHome()).isEqualTo(foo); - - options = options.jdkHome(foo.toPath()); - assertThat(options.jdkHome()).isEqualTo(foo); - - options.jdkHome(foo.getAbsolutePath()); - assertThat(options.jdkHome().getAbsolutePath()).isEqualTo(foo.getAbsolutePath()); - } - - @Test - void testKotlinHome() { - var foo = new File("foo.txt"); - var options = new CompileOptions(); - - options.kotlinHome(foo); - assertThat(options.kotlinHome()).isEqualTo(foo); - - options = options.kotlinHome(foo.toPath()); - assertThat(options.kotlinHome()).isEqualTo(foo); - - options.kotlinHome(foo.getAbsolutePath()); - assertThat(options.kotlinHome().getAbsolutePath()).isEqualTo(foo.getAbsolutePath()); - } - - @Test - void testOptions() { - var options = new CompileOptions() - .advancedOptions("xopt1", "xopt2") - .apiVersion("11") - .argFile(Path.of("args.txt")) - .classpath("classpath") - .expression("expression") - .includeRuntime(true) - .javaParameters(true) - .jdkHome("jdk-home") - .jdkRelease(22) - .jvmTarget("9") - .kotlinHome("kotlin-home") - .languageVersion("1.0") - .moduleName("module") - .noJdk(true) - .noReflect(true) - .noStdLib(true) - .noWarn(true) - .optIn("opt1", "opt2") - .options("-foo", "-bar") - .path(Path.of("path")) - .plugin("id", "name", "value") - .progressive(true) - .scriptTemplates("name", "name2") - .verbose(true) - .wError(true) - .wExtra(true); - - try (var softly = new AutoCloseableSoftAssertions()) { - softly.assertThat(options.advancedOptions()).containsExactly("xopt1", "xopt2"); - softly.assertThat(options.apiVersion()).isEqualTo("11"); - softly.assertThat(options.argFile()).containsExactly(new File("args.txt")); - softly.assertThat(options.classpath()).containsExactly(new File("classpath")); - softly.assertThat(options.expression()).isEqualTo("expression"); - softly.assertThat(options.isIncludeRuntime()).isTrue(); - softly.assertThat(options.isJavaParameters()).isTrue(); - softly.assertThat(options.isNoJdk()).isTrue(); - softly.assertThat(options.isNoReflect()).isTrue(); - softly.assertThat(options.isNoStdLib()).isTrue(); - softly.assertThat(options.isNoWarn()).isTrue(); - softly.assertThat(options.isProgressive()).isTrue(); - softly.assertThat(options.isVerbose()).isTrue(); - softly.assertThat(options.jdkHome()).isEqualTo(new File("jdk-home")); - softly.assertThat(options.jdkRelease()).isEqualTo("22"); - softly.assertThat(options.jvmTarget()).isEqualTo("9"); - softly.assertThat(options.kotlinHome()).isEqualTo(new File("kotlin-home")); - softly.assertThat(options.languageVersion()).isEqualTo("1.0"); - softly.assertThat(options.moduleName()).isEqualTo("module"); - softly.assertThat(options.optIn()).containsExactly("opt1", "opt2"); - softly.assertThat(options.options()).containsExactly("-foo", "-bar"); - softly.assertThat(options.path()).isEqualTo(new File("path")); - softly.assertThat(options.plugin()).containsExactly("id:name:value"); - softly.assertThat(options.scriptTemplates()).containsExactly("name", "name2"); - softly.assertThat(options.isWError()).isTrue(); - softly.assertThat(options.isWExtra()).isTrue(); - } - } -} diff --git a/src/test/java/rife/bld/extension/kotlin/JvmOptionsTest.java b/src/test/java/rife/bld/extension/kotlin/JvmOptionsTest.java deleted file mode 100644 index 6f8474f..0000000 --- a/src/test/java/rife/bld/extension/kotlin/JvmOptionsTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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.kotlin; - -import org.junit.jupiter.api.Test; -import rife.bld.extension.CompileKotlinOperation; - -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - -@SuppressWarnings("PMD.AvoidDuplicateLiterals") -class JvmOptionsTest { - @Test - void testop() { - var op = new CompileKotlinOperation().jvmOptions(new JvmOptions().enableNativeAccess(JvmOptions.ALL_UNNAMED)); - assertThat(op.jvmOptions()).as(JvmOptions.ALL_UNNAMED).containsExactly("--enable-native-access=ALL-UNNAMED"); - - op = new CompileKotlinOperation().jvmOptions(new JvmOptions().enableNativeAccess("m1", "m2")); - assertThat(op.jvmOptions()).as("m1,m2").containsExactly("--enable-native-access=m1,m2"); - } - - @Test - void testEnableNativeAccess() { - var options = new JvmOptions().enableNativeAccess(JvmOptions.ALL_UNNAMED); - assertThat(options).as(JvmOptions.ALL_UNNAMED).containsExactly("--enable-native-access=ALL-UNNAMED"); - - options = new JvmOptions().enableNativeAccess("m1"); - assertThat(options).as("m1").containsExactly("--enable-native-access=m1"); - - options = new JvmOptions().enableNativeAccess("m1", "m2"); - assertThat(options).as("m1,m2").containsExactly("--enable-native-access=m1,m2"); - } - - @Test - void testIllegalNativeAccess() { - var options = new JvmOptions().illegalNativeAccess(JvmOptions.NativeAccess.ALLOW); - assertThat(options).as("ALLOW").containsExactly("--illegal-native-access=allow"); - - options = new JvmOptions().illegalNativeAccess(JvmOptions.NativeAccess.DENY); - assertThat(options).as("DENY").containsExactly("--illegal-native-access=deny"); - - options = new JvmOptions().illegalNativeAccess(JvmOptions.NativeAccess.WARN); - assertThat(options).as("WARN").containsExactly("--illegal-native-access=warn"); - } - - @Test - void testJvmOptions() { - var op = new CompileKotlinOperation().jvmOptions("option1", "option2"); - assertThat(op.jvmOptions()).as("option1,option2").containsExactly("option1", "option2"); - - op = new CompileKotlinOperation().jvmOptions(List.of("option1", "option2")); - assertThat(op.jvmOptions()).as("List.of(option1,option2)").containsExactly("option1", "option2"); - - op = op.jvmOptions(new JvmOptions().enableNativeAccess(JvmOptions.ALL_UNNAMED)); - assertThat(op.jvmOptions()).as("List.of(option1,option2,ALL_UNNAMED)") - .containsExactly("option1", "option2", "--enable-native-access=ALL-UNNAMED"); - - op = op.jvmOptions(new JvmOptions().illegalNativeAccess(JvmOptions.NativeAccess.ALLOW)); - assertThat(op.jvmOptions()).as("allow") - .containsExactly("option1", "option2", "--enable-native-access=ALL-UNNAMED", - "--illegal-native-access=allow"); - } -} diff --git a/src/test/resources/argfile.txt b/src/test/resources/argfile.txt deleted file mode 100644 index d128d62..0000000 --- a/src/test/resources/argfile.txt +++ /dev/null @@ -1,3 +0,0 @@ --Xjdk-release=17 -no-reflect - --progressive diff --git a/src/test/resources/argfile2.txt b/src/test/resources/argfile2.txt deleted file mode 100644 index 93f9181..0000000 --- a/src/test/resources/argfile2.txt +++ /dev/null @@ -1 +0,0 @@ --include-runtime \ No newline at end of file diff --git a/src/test/resources/kotlinc-args.txt b/src/test/resources/kotlinc-args.txt deleted file mode 100644 index e764231..0000000 --- a/src/test/resources/kotlinc-args.txt +++ /dev/null @@ -1,26 +0,0 @@ -@ --api-version --classpath --d --expression --include-runtime --J --java-parameters --jdk-home --jvm-target --kotlin-home --language-version --module-name --no-jdk --no-reflect --no-stdlib --nowarn --opt-in --P --progressive --script --script-templates --verbose --Werror --Wextra --X