diff --git a/README.md b/README.md index eb79334..7902300 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ To compile the source code located in `src/main/kotlin` and `src/test/kotlin` fr public void compile() throws IOException { new CompileKotlinOperation() .fromProject(this) - .compileOptions("-verbose") + .compileOptions(new CompileKotlinOptions().verbose(true)) .execute(); } ``` diff --git a/examples/src/bld/java/com/example/ExampleBuild.java b/examples/src/bld/java/com/example/ExampleBuild.java index fa93f17..5a8bac6 100644 --- a/examples/src/bld/java/com/example/ExampleBuild.java +++ b/examples/src/bld/java/com/example/ExampleBuild.java @@ -3,6 +3,7 @@ package com.example; import rife.bld.BaseProject; import rife.bld.BuildCommand; import rife.bld.extension.CompileKotlinOperation; +import rife.bld.extension.CompileKotlinOptions; import rife.bld.extension.dokka.DokkaOperation; import rife.bld.extension.dokka.LoggingLevel; import rife.bld.extension.dokka.OutputFormat; @@ -53,7 +54,7 @@ public class ExampleBuild extends BaseProject { public void compile() throws IOException { new CompileKotlinOperation() .fromProject(this) - .compileOptions("-verbose") + .compileOptions(new CompileKotlinOptions().verbose(true)) .execute(); } diff --git a/src/main/java/rife/bld/extension/CompileKotlinOperation.java b/src/main/java/rife/bld/extension/CompileKotlinOperation.java index 2618da4..cdc8141 100644 --- a/src/main/java/rife/bld/extension/CompileKotlinOperation.java +++ b/src/main/java/rife/bld/extension/CompileKotlinOperation.java @@ -38,7 +38,6 @@ public class CompileKotlinOperation extends AbstractOperation compileMainClasspath_ = new ArrayList<>(); - private final Collection compileOptions_ = new ArrayList<>(); private final Collection compileTestClasspath_ = new ArrayList<>(); private final Collection mainSourceDirectories_ = new ArrayList<>(); private final Collection mainSourceFiles_ = new ArrayList<>(); @@ -46,6 +45,7 @@ public class CompileKotlinOperation extends AbstractOperation testSourceFiles_ = new ArrayList<>(); private File buildMainDirectory_; private File buildTestDirectory_; + private CompileKotlinOptions compileOptions_; public static Collection getKotlinFileList(File directory) { if (directory == null) { @@ -136,34 +136,14 @@ public class CompileKotlinOperation extends AbstractOperation options) { - compileOptions_.addAll(options); + public CompileKotlinOperation compileOptions(CompileKotlinOptions options) { + compileOptions_ = options; return this; } - /** - * Provides the compilation options to pass to the {@code kotlinc} compiler. - * - * @param options one or more compiler options - * @return this operation instance - */ - public CompileKotlinOperation compileOptions(String... options) { - compileOptions_.addAll(Arrays.asList(options)); - return this; - } - - /** - * Retrieves the list of compilation options for the {@code kotlinc} compiler. - * - * @return the list of compiler options - */ - public Collection compileOptions() { - return compileOptions_; - } - /** * Provides entries for the test compilation classpath. * @@ -249,7 +229,9 @@ public class CompileKotlinOperation extends AbstractOperation args.add(f.getAbsolutePath())); @@ -301,10 +283,6 @@ public class CompileKotlinOperation extends AbstractOperationErik 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 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 class 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 class 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 class 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-version + if (apiVersion_ != null) { + 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 (jvmTarget_ != null) { + 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_); + } + + // jdk-release + if (jdkRelease_ != null) { + args.add("-Xjdk-release=" + jdkRelease_); + } + + // kotlin-home + if (kotlinHome_ != null) { + args.add("-kotlin-home"); + args.add(kotlinHome_); + } + + // language-version + if (languageVersion_ != null) { + args.add("-language-version"); + args.add(languageVersion_); + } + + // module-name + if (moduleName_ != null) { + args.add("-module-name"); + args.add(moduleName_); + } + + // no-jdk + if (noJdk_) { + args.add("-no-jdk"); + } + + // no-reflect + if (noReflect_) { + args.add("-no-reflect"); + } + + // no-warn + if (noWarn_) { + args.add("-no-warn"); + } + + // opt-in + if (!optIn_.isEmpty()) { + optIn_.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_); + } + + // plugin + if (!plugin_.isEmpty()) { + plugin_.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 class 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 class instance + */ + public CompileKotlinOptions classpath(Collection paths) { + classpath_.addAll(paths); + return this; + } + + /** + * 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 class 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 class 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 JAVA_HOME.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 class 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 class instance + */ + public CompileKotlinOptions jdkRelease(String version) { + jdkRelease_ = 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 class instance + */ + public CompileKotlinOptions jvmTarget(String target) { + jvmTarget_ = target; + return this; + } + + /** + * Enable verbose logging output which includes details of the compilation process. + * + * @param path the Kotlin home path + * @return this class 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 class 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 class 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 class 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 class instance + */ + public CompileKotlinOptions noReflect(boolean noReflect) { + noReflect_ = noReflect; + return this; + } + + /** + * Suppress the compiler from displaying warnings during compilation. + * + * @param noWarn {@code true} or {@code false} + * @return this class 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 class 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 class instance + */ + public CompileKotlinOptions optIn(Collection annotations) { + optIn_.addAll(annotations); + return this; + } + + /** + * Specified additional compiler options. + * + * @param options one or more compiler options + * @return this class instance + */ + public CompileKotlinOptions options(String... options) { + options_.addAll(List.of(options)); + return this; + } + + /** + * Specified additional compiler options. + * + * @param options list of compiler options + * @return this class 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 class 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 class instance + */ + public CompileKotlinOptions path(String path) { + path_ = path; + return this; + } + + /** + * Enable verbose logging output which includes details of the compilation process. + * + * @param id the plugin + * @param optionName the plugin option name + * @param value the plugin option value + */ + 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 class 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 class 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 class 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 class 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 class instance + */ + public CompileKotlinOptions wErrpr(boolean wError) { + wError_ = wError; + return this; + } +} diff --git a/src/main/java/rife/bld/extension/dokka/DokkaOperation.java b/src/main/java/rife/bld/extension/dokka/DokkaOperation.java index 42ecfe8..4f25058 100644 --- a/src/main/java/rife/bld/extension/dokka/DokkaOperation.java +++ b/src/main/java/rife/bld/extension/dokka/DokkaOperation.java @@ -229,7 +229,7 @@ public class DokkaOperation extends AbstractProcessOperation { /** * Sets whether to fail documentation generation if Dokka has emitted a warning or an error. * - * @param failOnWarning the fail on warning ;toggle + * @param failOnWarning {@code true} or {@code false} * @return this operation instance */ public DokkaOperation failOnWarning(Boolean failOnWarning) { @@ -397,7 +397,7 @@ public class DokkaOperation extends AbstractProcessOperation { * Sets whether to suppress obvious functions such as inherited from {@code kotlin.Any} and * {@link java.lang.Object java.lang.Object}. * - * @param noSuppressObviousFunctions the suppress toggle + * @param noSuppressObviousFunctions {@code true} or {@code false} * @return this operation instance */ public DokkaOperation noSuppressObviousFunctions(Boolean noSuppressObviousFunctions) { @@ -529,7 +529,7 @@ public class DokkaOperation extends AbstractProcessOperation { /** * Sets whether to suppress inherited members that aren't explicitly overridden in a given class. * - * @param suppressInheritedMembers the suppress toggle + * @param suppressInheritedMembers {@code true} or {@code false} * @return this operation instance */ public DokkaOperation suppressInheritedMembers(Boolean suppressInheritedMembers) { diff --git a/src/main/java/rife/bld/extension/dokka/SourceSet.java b/src/main/java/rife/bld/extension/dokka/SourceSet.java index 6340602..f12222d 100644 --- a/src/main/java/rife/bld/extension/dokka/SourceSet.java +++ b/src/main/java/rife/bld/extension/dokka/SourceSet.java @@ -355,7 +355,7 @@ public class SourceSet { /** * Sets whether to generate links to JDK Javadocs. * - * @param noJdkLink the no JDK link toggle + * @param noJdkLink {@code true} or {@code false} * @return this operation instance */ public SourceSet noJdkLink(Boolean noJdkLink) { @@ -366,7 +366,7 @@ public class SourceSet { /** * Sets whether to create pages for empty packages. * - * @param noSkipEmptyPackages the no skip empty packages toggle + * @param noSkipEmptyPackages {@code true} or {@code false} * @return this operation instance */ public SourceSet noSkipEmptyPackages(boolean noSkipEmptyPackages) { @@ -377,7 +377,7 @@ public class SourceSet { /** * Sets whether to generate links to Standard library. * - * @param noStdlibLink the no std lib link toggle + * @param noStdlibLink {@code true} or {@code false} * @return this operation instance */ public SourceSet noStdlibLink(Boolean noStdlibLink) { @@ -426,7 +426,7 @@ public class SourceSet { /** * Sets Wwether to report undocumented declarations. * - * @param reportUndocumented the report undocumented toggle + * @param reportUndocumented {@code true} or {@code false} * @return this operation instance */ public SourceSet reportUndocumented(Boolean reportUndocumented) { @@ -459,7 +459,7 @@ public class SourceSet { /** * Sets whether to skip deprecated declarations. * - * @param skipDeprecated the skip deprecated toggle + * @param skipDeprecated {@code true} or {@code false} * @return this operation instance */ public SourceSet skipDeprecated(boolean skipDeprecated) { diff --git a/src/test/java/rife/bld/extension/CompileKotlinOperationTest.java b/src/test/java/rife/bld/extension/CompileKotlinOperationTest.java index 8acc57e..bb23cc5 100644 --- a/src/test/java/rife/bld/extension/CompileKotlinOperationTest.java +++ b/src/test/java/rife/bld/extension/CompileKotlinOperationTest.java @@ -68,7 +68,7 @@ class CompileKotlinOperationTest { } var op = new CompileKotlinOperation() - .compileOptions("-verbose") + .compileOptions(new CompileKotlinOptions().verbose(true)) .buildMainDirectory(mainDir) .buildTestDirectory(testDir) .compileMainClasspath(compileJars) 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..64c07cf --- /dev/null +++ b/src/test/java/rife/bld/extension/CompileKotlinOptionsTest.java @@ -0,0 +1,111 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package rife.bld.extension; + +import org.junit.jupiter.api.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")) + .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) + .wErrpr(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))); + } +}