port the worker files to kotlin and add bootstrap macros.
diff --git a/.bazelproject b/.bazelproject
index 2035d82..7828fba 100644
--- a/.bazelproject
+++ b/.bazelproject
@@ -17,8 +17,8 @@
.
targets:
- //kotlin/workers/...
- -//tests/smoke/...
+ //kotlin/workers:worker_for_ide
+ //kotlin/workers:unittests
test_sources:
*/unittests/*
diff --git a/kotlin/workers/BUILD b/kotlin/workers/BUILD
index 342ddaf..622afeb 100644
--- a/kotlin/workers/BUILD
+++ b/kotlin/workers/BUILD
@@ -11,28 +11,37 @@
# 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.
-java_library(
- name = "lib",
- srcs = glob(["src/**/*.java"]),
+load("//kotlin/workers:bootstrap.bzl", "kotlin_worker_lib")
+
+kotlin_worker_lib(
+ srcs = glob(["src/**/*.kt"]),
+ args = ["-jvm-target", "1.8"],
deps = [
"//kotlin/workers/proto",
- "@com_github_jetbrains_kotlin//:preloader"
+ "@com_github_jetbrains_kotlin//:preloader",
+ "@io_bazel_rules_kotlin_protobuf_protobuf_java//jar",
],
- exports = ["//kotlin/workers/proto"],
- visibility = ["//visibility:private"]
+ exports = [
+ "//kotlin/workers/proto"
+ ],
+ runtime_deps = [
+ "@com_github_jetbrains_kotlin//:kotlin-stdlib",
+ "@com_github_jetbrains_kotlin//:kotlin-stdlib-jdk7",
+ "@com_github_jetbrains_kotlin//:kotlin-stdlib-jdk8"
+ ]
)
java_binary(
name = "compiler_jvm",
main_class = "io.bazel.ruleskotlin.workers.compilers.jvm.KotlinJvmBuilder",
visibility = ["//visibility:public"],
- runtime_deps = ["lib"]
+ runtime_deps = [":worker_lib"]
)
java_test(
name = "unittests",
test_class = "io.bazel.ruleskotlin.workers.compilers.jvm.utils.JdepsParserTest",
srcs = glob(["unittests/**/*.java"]),
- deps = ["lib"],
+ deps = [":worker_lib"],
size = "small"
)
\ No newline at end of file
diff --git a/kotlin/workers/bootstrap.bzl b/kotlin/workers/bootstrap.bzl
new file mode 100644
index 0000000..dbdc866
--- /dev/null
+++ b/kotlin/workers/bootstrap.bzl
@@ -0,0 +1,87 @@
+# Copyright 2018 The Bazel Authors. All rights reserved.
+#
+# 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
+#
+# http://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.
+load("//kotlin:kotlin.bzl", _for_ide = "kotlin_library")
+
+_HEADER = """
+function join_by { local IFS="$$1"; shift; echo "$$*"; }
+
+CP=$$(join_by : $(locations :%s))
+"""
+
+# This is kept arround incase it's needed -- there shouldn't be a need for mixed compilation, but just in case.
+def _gen_mixed_cmd(name, args):
+ return _HEADER + ("""
+ARGS="-Xcompile-java -Xuse-javac %s"
+
+mkdir -p compile_classes
+
+JAVA_HOME=external/local_jdk ./$(location @com_github_jetbrains_kotlin//:kotlinc) -cp $${CP} -d compile_classes $${ARGS} $(SRCS)
+
+jar cf $(OUTS) -C compile_classes .
+
+rm -rf compile_classes
+""") % (name, args)
+
+def _gen_cmd(name, args):
+ return (_HEADER + """
+ARGS="%s"
+
+JAVA_HOME=external/local_jdk ./$(location @com_github_jetbrains_kotlin//:kotlinc) -cp $${CP} -d $(OUTS) $${ARGS} $(SRCS)
+""") % (name,args)
+
+
+
+
+def kotlin_worker_lib(srcs =[], args = [], deps=[], runtime_deps=[], exports=[]):
+ name = "worker"
+ dep_label = name + "_deps"
+ jar_file_label = name + "_file"
+ jar_name = name+".jar"
+ libary_label = name + "_lib"
+
+ # Dummy target loaded by `kotlin_library` so intellij can understand the sources.
+ _for_ide(
+ name = "for_ide",
+ srcs = srcs,
+ deps = deps,
+ runtime_deps = runtime_deps,
+ exports = exports,
+ visibility=["//visibility:private"],
+ )
+
+ native.filegroup(
+ name = dep_label,
+ srcs = deps,
+ visibility = ["//visibility:private"]
+ )
+ native.genrule(
+ name = jar_file_label,
+ tools = [
+ "@com_github_jetbrains_kotlin//:home",
+ "@com_github_jetbrains_kotlin//:kotlinc",
+ "@local_jdk//:jdk",
+ dep_label
+ ] + deps,
+ srcs = srcs,
+ outs = [jar_name],
+ cmd = _gen_cmd(dep_label, " ".join(args)),
+ visibility = ["//visibility:private"]
+ )
+ native.java_import(
+ name = libary_label,
+ jars = [jar_name],
+ exports = exports,
+ runtime_deps = (depset(runtime_deps) + exports + deps).to_list(),
+ visibility = ["//visibility:private"]
+ )
\ No newline at end of file
diff --git a/kotlin/workers/proto/BUILD b/kotlin/workers/proto/BUILD
index ebf55a8..e5770b9 100644
--- a/kotlin/workers/proto/BUILD
+++ b/kotlin/workers/proto/BUILD
@@ -19,4 +19,13 @@
],
exports = ["@io_bazel_rules_kotlin_protobuf_protobuf_java//jar"],
visibility = ["//kotlin/workers:__subpackages__"]
+)
+
+filegroup(
+ name = "files",
+ srcs = [
+ "jars/libdeps_proto-speed.jar",
+ "jars/libworker_protocol_proto-speed.jar"
+ ],
+ visibility = ["//kotlin/workers:__subpackages__"]
)
\ No newline at end of file
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/BazelWorker.java b/kotlin/workers/src/io/bazel/ruleskotlin/workers/BazelWorker.java
deleted file mode 100644
index 6ee7f1b..0000000
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/BazelWorker.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright 2018 The Bazel Authors. All rights reserved.
- *
- * 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
- *
- * http://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 io.bazel.ruleskotlin.workers;
-
-
-import com.google.devtools.build.lib.worker.WorkerProtocol;
-import io.bazel.ruleskotlin.workers.utils.IOUtils;
-
-import java.io.*;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-/**
- * Bazel worker runner.
- * <p>
- * <p>This class adapts a traditional command line program so it can be spawned by Bazel as a
- * persistent worker process that handles multiple invocations per JVM. It will also be backwards
- * compatible with being run as a normal single-invocation command.
- *
- * @param <T> delegate program type
- */
-public final class BazelWorker<T extends CommandLineProgram> implements CommandLineProgram {
- private final CommandLineProgram delegate;
- private final String mnemonic;
- private final PrintStream output;
-
- public BazelWorker(T delegate, PrintStream output, String mnemonic) {
- this.delegate = delegate;
- this.output = output;
- this.mnemonic = mnemonic;
- }
-
- @Override
- public Integer apply(List<String> args) {
- for (String arg : args) {
- if (arg.equals("--persistent_worker")) {
- return runAsPersistentWorker(args);
- }
- }
- return delegate.apply(loadArguments(args, false));
- }
-
- @SuppressWarnings("unused")
- private int runAsPersistentWorker(List<String> ignored) {
- InputStream realStdIn = System.in;
- PrintStream realStdOut = System.out;
- PrintStream realStdErr = System.err;
- try (InputStream emptyIn = new ByteArrayInputStream(new byte[0]);
- ByteArrayOutputStream buffer = new ByteArrayOutputStream();
- PrintStream ps = new PrintStream(buffer)) {
- System.setIn(emptyIn);
- System.setOut(ps);
- System.setErr(ps);
- while (true) {
- WorkerProtocol.WorkRequest request = WorkerProtocol.WorkRequest.parseDelimitedFrom(realStdIn);
- if (request == null) {
- return 0;
- }
- int exitCode;
-
- try {
- exitCode = delegate.apply(loadArguments(request.getArgumentsList(), true));
- } catch (RuntimeException e) {
- if (wasInterrupted(e)) {
- return 0;
- }
- System.err.println(
- "ERROR: Worker threw uncaught exception with args: " +
- request.getArgumentsList().stream().collect(Collectors.joining(" ")));
- e.printStackTrace(System.err);
- exitCode = 1;
- }
- WorkerProtocol.WorkResponse.newBuilder()
- .setOutput(buffer.toString())
- .setExitCode(exitCode)
- .build()
- .writeDelimitedTo(realStdOut);
- realStdOut.flush();
- buffer.reset();
- System.gc(); // be a good little worker process and consume less memory when idle
- }
- } catch (IOException | RuntimeException e) {
- if (wasInterrupted(e)) {
- return 0;
- }
- throw new RuntimeException(e);
- } finally {
- System.setIn(realStdIn);
- System.setOut(realStdOut);
- System.setErr(realStdErr);
- }
- }
-
- private List<String> loadArguments(List<String> args, boolean isWorker) {
- if (args.size() > 0) {
- String lastArg = args.get(args.size() - 1);
-
- if (lastArg.startsWith("@")) {
- String pathElement = lastArg.substring(1);
- Path flagFile = Paths.get(pathElement);
- if ((isWorker && lastArg.startsWith("@@")) || Files.exists(flagFile)) {
- if (!isWorker && !mnemonic.isEmpty()) {
- output.printf(
- "HINT: %s will compile faster if you run: "
- + "echo \"build --strategy=%s=worker\" >>~/.bazelrc\n",
- mnemonic, mnemonic);
- }
- try {
- return Files.readAllLines(flagFile, UTF_8);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- }
- }
- return args;
- }
-
- private boolean wasInterrupted(Throwable e) {
- Throwable cause = IOUtils.getRootCause(e);
- if (cause instanceof InterruptedException
- || cause instanceof InterruptedIOException) {
- output.println("Terminating worker due to interrupt signal");
- return true;
- }
- return false;
- }
-}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/BazelWorker.kt b/kotlin/workers/src/io/bazel/ruleskotlin/workers/BazelWorker.kt
new file mode 100644
index 0000000..0aa3f75
--- /dev/null
+++ b/kotlin/workers/src/io/bazel/ruleskotlin/workers/BazelWorker.kt
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2018 The Bazel Authors. All rights reserved.
+ *
+ * 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
+ *
+ * http://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 io.bazel.ruleskotlin.workers
+
+
+import com.google.devtools.build.lib.worker.WorkerProtocol
+import io.bazel.ruleskotlin.workers.utils.rootCause
+import java.io.*
+import java.nio.charset.StandardCharsets.UTF_8
+import java.nio.file.Files
+import java.nio.file.Paths
+import java.util.stream.Collectors
+
+/**
+ * Bazel worker runner.
+ *
+ *
+ *
+ * This class adapts a traditional command line program so it can be spawned by Bazel as a
+ * persistent worker process that handles multiple invocations per JVM. It will also be backwards
+ * compatible with being run as a normal single-invocation command.
+ *
+ * @param <T> delegate program type
+</T> */
+class BazelWorker<T : CommandLineProgram>(private val delegate: T, private val output: PrintStream, private val mnemonic: String) : CommandLineProgram {
+ companion object {
+ private const val INTERUPTED_STATUS = 0
+ private const val ERROR_STATUS = 1
+ }
+
+ override fun apply(args: List<String>): Int {
+ return if (args.contains("--persistent_worker"))
+ runAsPersistentWorker(args)
+ else delegate.apply(loadArguments(args, false))
+ }
+
+ @Suppress("UNUSED_PARAMETER")
+ private fun runAsPersistentWorker(ignored: List<String>): Int {
+ val realStdIn = System.`in`
+ val realStdOut = System.out
+ val realStdErr = System.err
+ try {
+ ByteArrayInputStream(ByteArray(0)).use { emptyIn ->
+ ByteArrayOutputStream().use { buffer ->
+ PrintStream(buffer).use { ps ->
+ System.setIn(emptyIn)
+ System.setOut(ps)
+ System.setErr(ps)
+ while (true) {
+ val request = WorkerProtocol.WorkRequest.parseDelimitedFrom(realStdIn) ?: return 0
+ var exitCode: Int
+
+ exitCode = try {
+ delegate.apply(loadArguments(request.argumentsList, true))
+ } catch (e: RuntimeException) {
+ if (wasInterrupted(e)) {
+ return INTERUPTED_STATUS
+ }
+ System.err.println(
+ "ERROR: Worker threw uncaught exception with args: " + request.argumentsList.stream().collect(Collectors.joining(" ")))
+ e.printStackTrace(System.err)
+ ERROR_STATUS
+ }
+
+ WorkerProtocol.WorkResponse.newBuilder()
+ .setOutput(buffer.toString())
+ .setExitCode(exitCode)
+ .build()
+ .writeDelimitedTo(realStdOut)
+ realStdOut.flush()
+ buffer.reset()
+ System.gc() // be a good little worker process and consume less memory when idle
+ }
+ }
+ }
+ }
+ } catch (e: IOException) {
+ if (wasInterrupted(e)) {
+ return INTERUPTED_STATUS
+ }
+ throw e
+ } catch (e: RuntimeException) {
+ if (wasInterrupted(e)) {
+ return INTERUPTED_STATUS
+ }
+ throw e
+ } finally {
+ System.setIn(realStdIn)
+ System.setOut(realStdOut)
+ System.setErr(realStdErr)
+ }
+ throw RuntimeException("drop through")
+ }
+
+ private fun loadArguments(args: List<String>, isWorker: Boolean): List<String> {
+ if (args.isNotEmpty()) {
+ val lastArg = args[args.size - 1]
+
+ if (lastArg.startsWith("@")) {
+ val pathElement = lastArg.substring(1)
+ val flagFile = Paths.get(pathElement)
+ if (isWorker && lastArg.startsWith("@@") || Files.exists(flagFile)) {
+ if (!isWorker && !mnemonic.isEmpty()) {
+ output.printf(
+ "HINT: %s will compile faster if you run: " + "echo \"build --strategy=%s=worker\" >>~/.bazelrc\n",
+ mnemonic, mnemonic)
+ }
+ try {
+ return Files.readAllLines(flagFile, UTF_8)
+ } catch (e: IOException) {
+ throw RuntimeException(e)
+ }
+
+ }
+ }
+ }
+ return args
+ }
+
+ private fun wasInterrupted(e: Throwable): Boolean {
+ val cause = e.rootCause
+ if (cause is InterruptedException || cause is InterruptedIOException) {
+ output.println("Terminating worker due to interrupt signal")
+ return true
+ }
+ return false
+ }
+}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/BuildAction.java b/kotlin/workers/src/io/bazel/ruleskotlin/workers/BuildAction.kt
similarity index 75%
rename from kotlin/workers/src/io/bazel/ruleskotlin/workers/BuildAction.java
rename to kotlin/workers/src/io/bazel/ruleskotlin/workers/BuildAction.kt
index 79dcd52..7805229 100644
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/BuildAction.java
+++ b/kotlin/workers/src/io/bazel/ruleskotlin/workers/BuildAction.kt
@@ -13,11 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package io.bazel.ruleskotlin.workers;
+package io.bazel.ruleskotlin.workers
-import java.util.function.Function;
-
-public interface BuildAction extends Function<Context, Integer> {
-
+abstract class BuildAction(@Suppress("unused") val id : String, protected val toolchain: KotlinToolchain) {
+ abstract operator fun invoke(ctx: Context): Int
}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/CommandLineProgram.java b/kotlin/workers/src/io/bazel/ruleskotlin/workers/CommandLineProgram.java
deleted file mode 100644
index 751241f..0000000
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/CommandLineProgram.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2018 The Bazel Authors. All rights reserved.
- *
- * 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
- *
- * http://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 io.bazel.ruleskotlin.workers;
-
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.function.Function;
-
-/**
- * Interface for command line programs.
- * <p>
- * <p>This is the same thing as a main function, except not static.
- */
-public interface CommandLineProgram extends Function<List<String>, Integer> {
-
- /**
- * Runs blocking program start to finish.
- * <p>
- * <p>This function might be called multiple times throughout the life of this object. Output
- * must be sent to {@link System#out} and {@link System#err}.
- *
- * @param args command line arguments
- * @return program exit code, i.e. 0 for success, non-zero for failure
- */
- @Override
- Integer apply(List<String> args);
-
- default Integer apply(String[] args) {
- return apply(Arrays.asList(args));
- }
-}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/CommandLineProgram.kt b/kotlin/workers/src/io/bazel/ruleskotlin/workers/CommandLineProgram.kt
new file mode 100644
index 0000000..5fb40fe
--- /dev/null
+++ b/kotlin/workers/src/io/bazel/ruleskotlin/workers/CommandLineProgram.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2018 The Bazel Authors. All rights reserved.
+ *
+ * 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
+ *
+ * http://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 io.bazel.ruleskotlin.workers
+
+
+/**
+ * Interface for command line programs.
+ *
+ * This is the same thing as a main function, except not static.
+ */
+interface CommandLineProgram {
+
+ /**
+ * Runs blocking program start to finish.
+ *
+ *
+ *
+ * This function might be called multiple times throughout the life of this object. Output
+ * must be sent to [System.out] and [System.err].
+ *
+ * @param args command line arguments
+ * @return program exit code, i.e. 0 for success, non-zero for failure
+ */
+ fun apply(args: List<String>): Int
+}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/CompileResult.java b/kotlin/workers/src/io/bazel/ruleskotlin/workers/CompileResult.java
deleted file mode 100644
index 49ea365..0000000
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/CompileResult.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright 2018 The Bazel Authors. All rights reserved.
- *
- * 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
- *
- * http://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 io.bazel.ruleskotlin.workers;
-
-import java.util.Optional;
-import java.util.function.Function;
-import java.util.function.Supplier;
-
-@FunctionalInterface
-public interface CompileResult {
- /**
- * The status of this operation.
- */
- default int status() {
- return 0;
- }
-
- default Optional<Exception> error() {
- return Optional.empty();
- }
-
- default void propogateError(String message) throws RuntimeException {
- error().ifPresent(e -> {
- throw new RuntimeException(message, e);
- });
- }
-
- static CompileResult just(final int status) {
- return new CompileResult() {
- @Override
- public int status() {
- return status;
- }
-
- @Override
- public Integer render(Context ctx) {
- return status;
- }
- };
- }
-
- static CompileResult error(final Exception error) {
- return new CompileResult() {
- @Override
- public int status() {
- return -1;
- }
-
- @Override
- public Optional<Exception> error() {
- return Optional.of(error);
- }
-
- @Override
- public Integer render(Context ctx) {
- throw new RuntimeException(error);
- }
- };
- }
-
- static CompileResult deferred(final int status, Function<Context, Integer> renderer) {
- return new CompileResult() {
- @Override
- public int status() {
- return status;
- }
-
- @Override
- public Integer render(Context ctx) {
- return renderer.apply(ctx);
- }
- };
- }
-
- final class Meta extends io.bazel.ruleskotlin.workers.Meta<CompileResult> {
- public Meta(String id) {
- super(id);
- }
-
- public CompileResult run(final Context ctx, Function<Context, Integer> op) {
- CompileResult result;
- try {
- result = CompileResult.just(op.apply(ctx));
- } catch (Exception e) {
- result = CompileResult.error(e);
- }
- return result;
- }
-
- public CompileResult runAndBind(final Context ctx, Function<Context, Integer> op) {
- CompileResult res = run(ctx, op);
- bind(ctx, res);
- return res;
- }
-
- public CompileResult runAndBind(final Context ctx, Supplier<Integer> op) {
- return runAndBind(ctx, (c) -> op.get());
- }
- }
-
- /**
- * Materialise the output of the compile result.
- *
- * @return the new status of the compile operation, this shouldn't make a failing status pass, but it could fail a compile operation.
- */
- Integer render(Context ctx);
-}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/CompileResult.kt b/kotlin/workers/src/io/bazel/ruleskotlin/workers/CompileResult.kt
new file mode 100644
index 0000000..6ac5a57
--- /dev/null
+++ b/kotlin/workers/src/io/bazel/ruleskotlin/workers/CompileResult.kt
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2018 The Bazel Authors. All rights reserved.
+ *
+ * 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
+ *
+ * http://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 io.bazel.ruleskotlin.workers
+
+import java.util.*
+
+interface CompileResult {
+ /**
+ * The status of this operation.
+ */
+ fun status(): Int {
+ return 0
+ }
+
+ fun error(): Optional<Exception> {
+ return Optional.empty()
+ }
+
+ @Throws(RuntimeException::class)
+ fun propogateError(message: String) {
+ error().ifPresent { e -> throw RuntimeException(message, e) }
+ }
+
+ class Meta(id: String) : io.bazel.ruleskotlin.workers.Meta<CompileResult>(id) {
+
+ fun run(ctx: Context, op: (Context) -> Int): CompileResult {
+ var result: CompileResult
+ try {
+ result = CompileResult.just(op(ctx))
+ } catch (e: Exception) {
+ result = CompileResult.error(e)
+ }
+
+ return result
+ }
+
+ fun runAndBind(ctx: Context, op: (Context) -> Int): CompileResult {
+ val res = run(ctx, op)
+ bind(ctx, res)
+ return res
+ }
+
+ // public CompileResult runAndBind(final Context ctx, Supplier<Integer> op) {
+ // return runAndBind(ctx, (c) -> op.get());
+ // }
+ }
+
+ /**
+ * Materialise the output of the compile result.
+ *
+ * @return the new status of the compile operation, this shouldn't make a failing status pass, but it could fail a compile operation.
+ */
+ fun render(ctx: Context): Int
+
+ companion object {
+
+ fun just(status: Int): CompileResult {
+ return object : CompileResult {
+ override fun status(): Int {
+ return status
+ }
+
+ override fun render(ctx: Context): Int {
+ return status
+ }
+ }
+ }
+
+ fun error(error: Exception): CompileResult {
+ return object : CompileResult {
+ override fun status(): Int {
+ return -1
+ }
+
+ override fun error(): Optional<Exception> {
+ return Optional.of(error)
+ }
+
+ override fun render(ctx: Context): Int {
+ throw RuntimeException(error)
+ }
+ }
+ }
+
+ fun deferred(status: Int, renderer: (Context) -> Int): CompileResult {
+ return object : CompileResult {
+ override fun status(): Int {
+ return status
+ }
+
+ override fun render(ctx: Context): Int {
+ return renderer(ctx)
+ }
+ }
+ }
+ }
+}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/Context.java b/kotlin/workers/src/io/bazel/ruleskotlin/workers/Context.java
deleted file mode 100644
index 5bb4fad..0000000
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/Context.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2018 The Bazel Authors. All rights reserved.
- *
- * 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
- *
- * http://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 io.bazel.ruleskotlin.workers;
-
-import java.util.*;
-import java.util.function.Consumer;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-public class Context {
- private final EnumMap<Flags, String> args = new EnumMap<>(Flags.class);
- private final Map<Meta<?>, Object> meta = new HashMap<>();
-
- private static final Map<String, Flags> ALL_FIELDS_MAP = Arrays.stream(Flags.values()).collect(Collectors.toMap(x -> x.name, x -> x));
- private static final Flags[] MANDATORY_FIELDS = Arrays.stream(Flags.values()).filter(x -> x.mandatory).toArray(Flags[]::new);
-
- private Context(List<String> args) {
- if (args.size() % 2 != 0) {
- throw new RuntimeException("args should be k,v pairs");
- }
-
- for (int i = 0; i < args.size() / 2; i++) {
- String flag = args.get(i * 2);
- String value = args.get((i * 2) + 1);
- Flags field = ALL_FIELDS_MAP.get(flag);
- if (field == null) {
- throw new RuntimeException("unrecognised arg: " + flag);
- }
- this.args.put(field, value);
- }
-
- for (Flags mandatoryField : MANDATORY_FIELDS) {
- if (!this.args.containsKey(mandatoryField)) {
- throw new RuntimeException("mandatory arg missing: " + mandatoryField.name);
- }
- }
- }
-
- public static Context from(List<String> args) {
- return new Context(args);
- }
-
- public EnumMap<Flags, String> of(Flags... fields) {
- EnumMap<Flags, String> result = new EnumMap<>(Flags.class);
- for (Flags field : fields) {
- String value = args.get(field);
- if (value != null) {
- result.put(field, value);
- }
- }
- return result;
- }
-
- public interface Action extends Consumer<Context> {
- }
-
- public void apply(Action... consumers) {
- Stream.of(consumers).forEach(c -> c.accept(this));
- }
-
-
- String get(Flags field) {
- return args.get(field);
- }
-
- @SuppressWarnings("unchecked")
- <T> T get(Meta<T> key) {
- return (T) meta.get(key);
- }
-
- @SuppressWarnings("unchecked")
- <T> T putIfAbsent(Meta<T> key, T value) {
- return (T) meta.putIfAbsent(key, value);
- }
-}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/Context.kt b/kotlin/workers/src/io/bazel/ruleskotlin/workers/Context.kt
new file mode 100644
index 0000000..1a42331
--- /dev/null
+++ b/kotlin/workers/src/io/bazel/ruleskotlin/workers/Context.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2018 The Bazel Authors. All rights reserved.
+ *
+ * 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
+ *
+ * http://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.
+ */
+@file:Suppress("UNCHECKED_CAST")
+
+package io.bazel.ruleskotlin.workers
+
+import java.util.*
+import java.util.stream.Stream
+
+class Context private constructor(args: List<String>) {
+ private val args = EnumMap<Flags, String>(Flags::class.java)
+ private val meta = HashMap<Meta<*>, Any>()
+
+ init {
+ if (args.size % 2 != 0) {
+ throw RuntimeException("args should be k,v pairs")
+ }
+
+ for (i in 0 until args.size / 2) {
+ val flag = args[i * 2]
+ val value = args[i * 2 + 1]
+ val field = ALL_FIELDS_MAP[flag] ?: throw RuntimeException("unrecognised arg: " + flag)
+ this.args[field] = value
+ }
+
+ MANDATORY_FIELDS.asSequence()
+ .filterNot { this.args.containsKey(it) }
+ .forEach { throw RuntimeException("mandatory arg missing: " + it.globalFlag) }
+ }
+
+ fun of(vararg fields: Flags): EnumMap<Flags, String> {
+ val result = EnumMap<Flags, String>(Flags::class.java)
+ for (field in fields) {
+ val value = args[field]
+ if (value != null) {
+ result[field] = value
+ }
+ }
+ return result
+ }
+
+ fun apply(vararg consumers: (Context) -> Unit) {
+ Stream.of(*consumers).forEach { it(this) }
+ }
+
+ internal operator fun get(field: Flags): String? = args[field]
+ internal operator fun <T : Any> get(key: Meta<T>): T? = meta[key] as T?
+ internal fun <T : Any> putIfAbsent(key: Meta<T>, value: T): T? = meta.putIfAbsent(key, value as Any) as T?
+
+ companion object {
+ private val ALL_FIELDS_MAP = Flags.values().map { it.globalFlag to Flags.valueOf(it.name) }.toMap()
+ private val MANDATORY_FIELDS = Flags.values().filter { x -> x.mandatory }
+
+ fun from(args: List<String>): Context {
+ return Context(args)
+ }
+ }
+}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/Flags.java b/kotlin/workers/src/io/bazel/ruleskotlin/workers/Flags.kt
similarity index 76%
rename from kotlin/workers/src/io/bazel/ruleskotlin/workers/Flags.java
rename to kotlin/workers/src/io/bazel/ruleskotlin/workers/Flags.kt
index 7aaa65a..fe20049 100644
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/Flags.java
+++ b/kotlin/workers/src/io/bazel/ruleskotlin/workers/Flags.kt
@@ -13,10 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package io.bazel.ruleskotlin.workers;
+package io.bazel.ruleskotlin.workers
-public enum Flags {
+enum class Flags(val globalFlag: String, val kotlinFlag: String?, internal val mandatory: Boolean) {
// flags that line up with the java builder.
LABEL(JavaBuilderFlags.TARGET_LABEL.flag, null, true),
OUTPUT_CLASSJAR(JavaBuilderFlags.OUTPUT.flag, null, true),
@@ -32,17 +32,5 @@
KOTLIN_LANGUAGE_VERSION("--kotlin_language_version", "-language-version", false),
KOTLIN_JVM_TARGET("--kotlin_jvm_target", "-jvm-target", false);
- public final String name;
- public final String kotlinFlag;
- final boolean mandatory;
-
- Flags(String name, String kotlinName, boolean mandatory) {
- this.name = name;
- this.kotlinFlag = kotlinName;
- this.mandatory = mandatory;
- }
-
- public String get(Context context) {
- return context.get(this);
- }
+ operator fun get(context: Context): String? = context[this]
}
\ No newline at end of file
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/JavaBuilderFlags.java b/kotlin/workers/src/io/bazel/ruleskotlin/workers/JavaBuilderFlags.kt
similarity index 88%
rename from kotlin/workers/src/io/bazel/ruleskotlin/workers/JavaBuilderFlags.java
rename to kotlin/workers/src/io/bazel/ruleskotlin/workers/JavaBuilderFlags.kt
index dcecc40..3287a27 100644
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/JavaBuilderFlags.java
+++ b/kotlin/workers/src/io/bazel/ruleskotlin/workers/JavaBuilderFlags.kt
@@ -13,13 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package io.bazel.ruleskotlin.workers;
+package io.bazel.ruleskotlin.workers
/**
* Flags used by the java builder.
*/
-@SuppressWarnings("unused")
-public enum JavaBuilderFlags {
+enum class JavaBuilderFlags(val flag: String) {
TARGET_LABEL("--target_label"),
CLASSPATH("--classpath"),
JAVAC_OPTS("--javacopts"),
@@ -51,11 +50,5 @@
POST_PROCESSOR("--post_processor"),
COMPRESS_JAR("--compress_jar"),
RULE_KIND("--rule_kind"),
- TEST_ONLY("--testonly");
-
- public final String flag;
-
- JavaBuilderFlags(String flag) {
- this.flag = flag;
- }
+ TEST_ONLY("--testonly")
}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/KotlinToolchain.java b/kotlin/workers/src/io/bazel/ruleskotlin/workers/KotlinToolchain.java
deleted file mode 100644
index 4f8e5c1..0000000
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/KotlinToolchain.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2018 The Bazel Authors. All rights reserved.
- *
- * 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
- *
- * http://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 io.bazel.ruleskotlin.workers;
-
-import io.bazel.ruleskotlin.workers.compilers.jvm.Locations;
-import org.jetbrains.kotlin.preloading.ClassPreloadingUtils;
-import org.jetbrains.kotlin.preloading.Preloader;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.lang.reflect.Method;
-import java.nio.file.Paths;
-import java.util.function.BiFunction;
-
-public final class KotlinToolchain {
- private static final Object[] NO_ARGS = new Object[]{};
- private final ClassLoader classLoader;
-
- public KotlinToolchain() throws IOException {
- this.classLoader = ClassPreloadingUtils.preloadClasses(
- Locations.KOTLIN_REPO.verifiedRelativeFiles(
- Paths.get("lib", "kotlin-compiler.jar")
- ),
- Preloader.DEFAULT_CLASS_NUMBER_ESTIMATE,
- Thread.currentThread().getContextClassLoader(),
- null
- );
- }
-
- public interface KotlinCompiler extends BiFunction<String[], PrintStream, Integer> {
- }
-
- /**
- * Load the Kotlin compiler and the javac tools.jar into a Preloading classLoader. The Kotlin compiler is invoked reflectively to eventually allow
- * toolchain replacement.
- */
- public KotlinCompiler kotlinCompiler() {
- try {
- Class<?> compilerClass = classLoader.loadClass("org.jetbrains.kotlin.cli.jvm.K2JVMCompiler");
- Class<?> exitCodeClass = classLoader.loadClass("org.jetbrains.kotlin.cli.common.ExitCode");
-
- Object compiler = compilerClass.newInstance();
- Method execMethod = compilerClass.getMethod("exec", PrintStream.class, String[].class);
- Method getCodeMethod = exitCodeClass.getMethod("getCode");
-
- return (args, stream) -> {
- final Object exitCodeInstance;
- try {
- exitCodeInstance = execMethod.invoke(compiler, stream, args);
- return (Integer) getCodeMethod.invoke(exitCodeInstance, NO_ARGS);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- };
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/KotlinToolchain.kt b/kotlin/workers/src/io/bazel/ruleskotlin/workers/KotlinToolchain.kt
new file mode 100644
index 0000000..6e7a2c8
--- /dev/null
+++ b/kotlin/workers/src/io/bazel/ruleskotlin/workers/KotlinToolchain.kt
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2018 The Bazel Authors. All rights reserved.
+ *
+ * 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
+ *
+ * http://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 io.bazel.ruleskotlin.workers
+
+import io.bazel.ruleskotlin.workers.utils.resolveVerified
+import io.bazel.ruleskotlin.workers.utils.verifiedRelativeFiles
+import org.jetbrains.kotlin.preloading.ClassPreloadingUtils
+import org.jetbrains.kotlin.preloading.Preloader
+import java.io.PrintStream
+import java.nio.file.Path
+import java.nio.file.Paths
+
+@Suppress("PropertyName")
+class KotlinToolchain {
+ companion object {
+ internal val JAVA_HOME = Paths.get("external", "local_jdk")
+ internal val KOTLIN_HOME = Paths.get("external", "com_github_jetbrains_kotlin")
+
+ internal val NO_ARGS = arrayOf<Any>()
+ }
+
+ val JAVAC_PATH = JAVA_HOME.resolveVerified("bin", "javac").toString()
+ val JAR_TOOL_PATH = JAVA_HOME.resolveVerified("bin", "jar").toString()
+ val JDEPS_PATH = JAVA_HOME.resolveVerified("bin", "jdeps").toString()
+ val KOTLIN_LIB_DIR: Path = KOTLIN_HOME.resolveVerified("lib").toPath()
+
+ private val kotlinPreloadJars = KOTLIN_LIB_DIR.verifiedRelativeFiles(
+ Paths.get("kotlin-compiler.jar")
+ )
+
+ val KOTLIN_STD_LIBS = arrayOf(
+ "kotlin-stdlib.jar",
+ "kotlin-stdlib-jdk7.jar",
+ "kotlin-stdlib-jdk8.jar"
+ )
+
+ private val classLoader: ClassLoader by lazy {
+ ClassPreloadingUtils.preloadClasses(
+ kotlinPreloadJars,
+ Preloader.DEFAULT_CLASS_NUMBER_ESTIMATE,
+ Thread.currentThread().contextClassLoader,
+ null
+ )
+ }
+
+ interface KotlinCompiler {
+ fun compile(args: Array<String>, out: PrintStream): Int
+ }
+
+ /**
+ * Load the Kotlin compiler into a Preloading classLoader.
+ */
+ val kotlinCompiler: KotlinCompiler by lazy {
+ val compilerClass = classLoader.loadClass("org.jetbrains.kotlin.cli.jvm.K2JVMCompiler")
+ val exitCodeClass = classLoader.loadClass("org.jetbrains.kotlin.cli.common.ExitCode")
+
+ val compiler = compilerClass.newInstance()
+ val execMethod = compilerClass.getMethod("exec", PrintStream::class.java, Array<String>::class.java)
+ val getCodeMethod = exitCodeClass.getMethod("getCode")
+
+ object : KotlinCompiler {
+ override fun compile(args: Array<String>, out: PrintStream): Int {
+ val exitCodeInstance: Any
+ try {
+ exitCodeInstance = execMethod.invoke(compiler, out, args)
+ return getCodeMethod.invoke(exitCodeInstance, *NO_ARGS) as Int
+ } catch (e: Exception) {
+ throw RuntimeException(e)
+ }
+ }
+ }
+ }
+}
+
+
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/Meta.java b/kotlin/workers/src/io/bazel/ruleskotlin/workers/Meta.java
deleted file mode 100644
index 94a0712..0000000
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/Meta.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2018 The Bazel Authors. All rights reserved.
- *
- * 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
- *
- * http://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 io.bazel.ruleskotlin.workers;
-
-import java.util.Optional;
-
-public class Meta<T> {
- private final String id;
-
- private final T defaultValue;
-
- public Meta(String id) {
- this.id = id;
- this.defaultValue = null;
- }
-
- @SuppressWarnings("unused")
- private Meta(String id, T defaultValue) {
- this.id = id;
- this.defaultValue = defaultValue;
- }
-
- /**
- * Gets a mandatory value.
- */
- public T mustGet(Context ctx) {
- T res = ctx.get(this);
- if(res == null) {
- assert defaultValue != null : "mandatory meta parameter missing in context and does not have a default value";
- return defaultValue;
- }
- return res;
- }
-
- /**
- * Gets an optional value, if it has not been bound the default value is used.
- */
- public Optional<T> get(Context ctx) {
- T res = ctx.get(this);
- if( res != null) {
- return Optional.of(res);
- } else if(defaultValue != null) {
- return Optional.of(defaultValue);
- } else {
- return Optional.empty();
- }
- }
-
- public void bind(Context ctx, T value) {
- if (ctx.putIfAbsent(this, value) != null) {
- throw new RuntimeException("attempting to change bound meta variable " + id);
- }
- }
-}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/Meta.kt b/kotlin/workers/src/io/bazel/ruleskotlin/workers/Meta.kt
new file mode 100644
index 0000000..a0aca11
--- /dev/null
+++ b/kotlin/workers/src/io/bazel/ruleskotlin/workers/Meta.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2018 The Bazel Authors. All rights reserved.
+ *
+ * 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
+ *
+ * http://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 io.bazel.ruleskotlin.workers
+
+open class Meta<T: Any>(
+ private val id: String,
+ private val defaultValue: T? = null
+) {
+ constructor(id: String) : this(id, null)
+
+ /**
+ * Gets a mandatory value.
+ */
+ fun mustGet(ctx: Context): T =
+ ctx[this] ?: checkNotNull(defaultValue) { "mandatory meta parameter missing in context and does not have a default value" }
+
+ /**
+ * Gets an optional value, if it has not been bound the default value is used.
+ */
+ operator fun get(ctx: Context): T? {
+ val res = ctx[this]
+ return when {
+ res != null -> res
+ defaultValue != null -> defaultValue
+ else -> null
+ }
+ }
+
+ fun bind(ctx: Context, value: T) { check(ctx.putIfAbsent(this, value) == null) { "attempting to change bound meta variable: $id " } }
+}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/KotlinJvmBuilder.java b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/KotlinJvmBuilder.java
deleted file mode 100644
index d6bdf85..0000000
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/KotlinJvmBuilder.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2018 The Bazel Authors. All rights reserved.
- *
- * 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
- *
- * http://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 io.bazel.ruleskotlin.workers.compilers.jvm;
-
-
-import io.bazel.ruleskotlin.workers.*;
-import io.bazel.ruleskotlin.workers.compilers.jvm.actions.*;
-
-import java.io.IOException;
-import java.util.List;
-
-/**
- * Bazel Kotlin Compiler worker.
- */
-public final class KotlinJvmBuilder implements CommandLineProgram {
- private final BuildAction[] compileActions;
-
- private KotlinJvmBuilder() {
- KotlinToolchain kotlinToolchain;
- try {
- kotlinToolchain = new KotlinToolchain();
- } catch (IOException e) {
- throw new RuntimeException("could not initialize toolchain", e);
- }
-
- compileActions = new BuildAction[]{
- Initialize.INSTANCE,
- new KotlinMainCompile(kotlinToolchain),
- new JavaMainCompile(),
- KotlinRenderClassCompileResult.INSTANCE,
- CreateOutputJar.INSTANCE,
- GenerateJdepsFile.INSTANCE,
- };
- }
-
- @Override
- public Integer apply(List<String> args) {
- Context context = Context.from(args);
- Integer exitCode = 0;
- for (BuildAction action : compileActions) {
- exitCode = action.apply(context);
- if (exitCode != 0)
- break;
- }
- return exitCode;
- }
-
- public static void main(String[] args) {
- KotlinJvmBuilder kotlinBuilder = new KotlinJvmBuilder();
- BazelWorker<KotlinJvmBuilder> kotlinCompilerBazelWorker = new BazelWorker<>(
- kotlinBuilder,
- System.err,
- "KotlinCompile"
- );
- System.exit(kotlinCompilerBazelWorker.apply(args));
- }
-}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/KotlinJvmBuilder.kt b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/KotlinJvmBuilder.kt
new file mode 100644
index 0000000..571bdd1
--- /dev/null
+++ b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/KotlinJvmBuilder.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2018 The Bazel Authors. All rights reserved.
+ *
+ * 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
+ *
+ * http://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 io.bazel.ruleskotlin.workers.compilers.jvm
+
+
+import io.bazel.ruleskotlin.workers.*
+import io.bazel.ruleskotlin.workers.compilers.jvm.actions.*
+
+import java.io.IOException
+
+/**
+ * Bazel Kotlin Compiler worker.
+ */
+class KotlinJvmBuilder private constructor() : CommandLineProgram {
+ private val compileActions: Array<BuildAction>
+
+ init {
+ val toolchain: KotlinToolchain
+ try {
+ toolchain = KotlinToolchain()
+ } catch (e: IOException) {
+ throw RuntimeException("could not initialize toolchain", e)
+ }
+
+ compileActions = arrayOf(
+ Initialize(toolchain),
+ KotlinMainCompile(toolchain),
+ JavaMainCompile(toolchain),
+ ProcessCompileResult(toolchain),
+ CreateOutputJar(toolchain),
+ GenerateJdepsFile(toolchain)
+ )
+ }
+
+ override fun apply(args: List<String>): Int {
+ val ctx = Context.from(args)
+ var exitCode = 0
+ for (action in compileActions) {
+ exitCode = action(ctx)
+ if (exitCode != 0)
+ break
+ }
+ return exitCode
+ }
+
+ companion object {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val kotlinBuilder = KotlinJvmBuilder()
+ val kotlinCompilerBazelWorker = BazelWorker(
+ kotlinBuilder,
+ System.err,
+ "KotlinCompile"
+ )
+ System.exit(kotlinCompilerBazelWorker.apply(args.toList()))
+ }
+ }
+}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/Locations.java b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/Locations.java
deleted file mode 100644
index c877564..0000000
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/Locations.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2018 The Bazel Authors. All rights reserved.
- *
- * 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
- *
- * http://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 io.bazel.ruleskotlin.workers.compilers.jvm;
-
-import java.io.File;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-public enum Locations {
- KOTLIN_REPO(Paths.get("external", "com_github_jetbrains_kotlin")),
- JAVA_HOME(Paths.get("external", "local_jdk"));
-
- private final Path path;
-
- Locations(Path path) {
- this.path = path;
- }
-
- public final File resolveVerified(String... parts) {
- return verified(path.resolve(Paths.get(parts[0], Arrays.copyOfRange(parts, 1, parts.length))));
- }
-
- /**
- * Return a stream of paths that are known to exists relative to this location.
- */
- public final List<File> verifiedRelativeFiles(Path... paths) {
- return Stream.of(paths).map(relative -> verified(path.resolve(relative))).collect(Collectors.toList());
- }
-
- private File verified(Path target) {
- File asFile = target.toFile();
- if (!asFile.exists()) {
- throw new RuntimeException("location " + this.name() + " did not have relative path file " + target);
- }
- return asFile;
- }
- }
\ No newline at end of file
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/Metas.java b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/Metas.java
deleted file mode 100644
index eb8ff54..0000000
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/Metas.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2018 The Bazel Authors. All rights reserved.
- *
- * 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
- *
- * http://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 io.bazel.ruleskotlin.workers.compilers.jvm;
-
-import io.bazel.ruleskotlin.workers.CompileResult;
-import io.bazel.ruleskotlin.workers.Meta;
-
-import java.nio.file.Path;
-import java.util.List;
-
-/**
- * Meta is a key to some compilation state,.
- */
-public class Metas {
- // mandatory: the package part of the label.
- public static final Meta<String> PKG = new Meta<>("package");
- // mandatory: The target part of the label.
- public static final Meta<String> TARGET = new Meta<>("target");
- // mandatory: the class staging directory.
- public static final Meta<Path> CLASSES_DIRECTORY = new Meta<>("class_directory");
- // mandatory: If this is non empty then it is a mixed mode operation.
- public static final Meta<List<String>> JAVA_SOURCES = new Meta<>("java_sources");
- // mandatory:
- public static final Meta<List<String>> ALL_SOURCES = new Meta<>("all_sources");
- // mandatory:
- public static final CompileResult.Meta KOTLINC_RESULT = new CompileResult.Meta("kotlin_compile_result");
- // optional: when not a mixed mode operation.
- public static final CompileResult.Meta JAVAC_RESULT = new CompileResult.Meta("javac_compile_result");
-}
\ No newline at end of file
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/Metas.kt b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/Metas.kt
new file mode 100644
index 0000000..6b56242
--- /dev/null
+++ b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/Metas.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2018 The Bazel Authors. All rights reserved.
+ *
+ * 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
+ *
+ * http://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 io.bazel.ruleskotlin.workers.compilers.jvm
+
+import io.bazel.ruleskotlin.workers.CompileResult
+import io.bazel.ruleskotlin.workers.Meta
+
+import java.nio.file.Path
+
+/**
+ * Meta is a key to some compilation state,.
+ */
+object Metas {
+ // mandatory: the package part of the label.
+ val PKG = Meta<String>("package")
+ // mandatory: The target part of the label.
+ val TARGET = Meta<String>("target")
+ // mandatory: the class staging directory.
+ val CLASSES_DIRECTORY = Meta<Path>("class_directory")
+ // mandatory: If this is non empty then it is a mixed mode operation.
+ val JAVA_SOURCES = Meta<List<String>>("java_sources")
+ // mandatory:
+ val ALL_SOURCES = Meta<List<String>>("all_sources")
+ // mandatory:
+ val KOTLINC_RESULT = CompileResult.Meta("kotlin_compile_result")
+ // optional: when not a mixed mode operation.
+ val JAVAC_RESULT = CompileResult.Meta("javac_compile_result")
+}
\ No newline at end of file
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/CreateOutputJar.java b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/CreateOutputJar.java
deleted file mode 100644
index aba021e..0000000
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/CreateOutputJar.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2018 The Bazel Authors. All rights reserved.
- *
- * 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
- *
- * http://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 io.bazel.ruleskotlin.workers.compilers.jvm.actions;
-
-
-import io.bazel.ruleskotlin.workers.BuildAction;
-import io.bazel.ruleskotlin.workers.Context;
-import io.bazel.ruleskotlin.workers.Flags;
-import io.bazel.ruleskotlin.workers.compilers.jvm.Locations;
-import io.bazel.ruleskotlin.workers.compilers.jvm.Metas;
-import io.bazel.ruleskotlin.workers.utils.IOUtils;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Create a jar from the classes.
- */
-public final class CreateOutputJar implements BuildAction {
- public static final CreateOutputJar INSTANCE = new CreateOutputJar();
- private static final String JAR_TOOL_PATH = Locations.JAVA_HOME.resolveVerified("bin", "jar").toString();
-
- private CreateOutputJar() {
- }
-
- @Override
- public Integer apply(Context ctx) {
- try {
- List<String> command = Arrays.asList(JAR_TOOL_PATH,
- "cf", Flags.OUTPUT_CLASSJAR.get(ctx),
- "-C", Metas.CLASSES_DIRECTORY.mustGet(ctx).toString(),
- ".");
- IOUtils.executeAndAwaitSuccess(10, command);
- } catch (Exception e) {
- throw new RuntimeException("unable to create class jar", e);
- }
- return 0;
- }
-}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/CreateOutputJar.kt b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/CreateOutputJar.kt
new file mode 100644
index 0000000..38545fa
--- /dev/null
+++ b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/CreateOutputJar.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2018 The Bazel Authors. All rights reserved.
+ *
+ * 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
+ *
+ * http://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 io.bazel.ruleskotlin.workers.compilers.jvm.actions
+
+
+import io.bazel.ruleskotlin.workers.BuildAction
+import io.bazel.ruleskotlin.workers.Context
+import io.bazel.ruleskotlin.workers.Flags
+import io.bazel.ruleskotlin.workers.KotlinToolchain
+import io.bazel.ruleskotlin.workers.compilers.jvm.Metas
+import io.bazel.ruleskotlin.workers.utils.executeAndAwaitSuccess
+
+/**
+ * Create a jar from the classes.
+ */
+class CreateOutputJar(toolchain: KotlinToolchain) : BuildAction("create output jar", toolchain) {
+ override fun invoke(ctx: Context): Int {
+ try {
+ executeAndAwaitSuccess(10,
+ toolchain.JAR_TOOL_PATH,
+ "cf", checkNotNull(Flags.OUTPUT_CLASSJAR[ctx]),
+ "-C", Metas.CLASSES_DIRECTORY.mustGet(ctx).toString(),
+ "."
+ )
+ } catch (e: Exception) {
+ throw RuntimeException("unable to create class jar", e)
+ }
+ return 0
+ }
+}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/GenerateJdepsFile.java b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/GenerateJdepsFile.java
deleted file mode 100644
index 683cce5..0000000
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/GenerateJdepsFile.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2018 The Bazel Authors. All rights reserved.
- *
- * 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
- *
- * http://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 io.bazel.ruleskotlin.workers.compilers.jvm.actions;
-
-import com.google.devtools.build.lib.view.proto.Deps;
-import io.bazel.ruleskotlin.workers.BuildAction;
-import io.bazel.ruleskotlin.workers.Context;
-import io.bazel.ruleskotlin.workers.compilers.jvm.Locations;
-import io.bazel.ruleskotlin.workers.compilers.jvm.utils.JdepsParser;
-import io.bazel.ruleskotlin.workers.utils.IOUtils;
-
-import java.io.FileOutputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.List;
-import java.util.function.Predicate;
-
-import static io.bazel.ruleskotlin.workers.Flags.*;
-
-
-public final class GenerateJdepsFile implements BuildAction {
- private static final String JDEPS_PATH = Locations.JAVA_HOME.resolveVerified("bin", "jdeps").toString();
-
- private static final Predicate<String> IS_KOTLIN_IMPLICIT = JdepsParser.pathSuffixMatchingPredicate(
- Paths.get("external", "com_github_jetbrains_kotlin", "lib"),
- "kotlin-stdlib.jar",
- "kotlin-stdlib-jdk7.jar",
- "kotlin-stdlib-jdk8.jar");
-
- public static final GenerateJdepsFile INSTANCE = new GenerateJdepsFile();
-
- private GenerateJdepsFile() {
- }
-
- @Override
- public Integer apply(Context ctx) {
- final String
- classJar = OUTPUT_CLASSJAR.get(ctx),
- classPath = CLASSPATH.get(ctx),
- output = OUTPUT_JDEPS.get(ctx);
- Deps.Dependencies jdepsContent;
- try {
- List<String> jdepLines = IOUtils.executeAndWaitOutput(10, JDEPS_PATH, "-cp", classPath, classJar);
- jdepsContent = JdepsParser.parse(
- LABEL.get(ctx),
- classJar,
- classPath,
- jdepLines.stream(),
- IS_KOTLIN_IMPLICIT
- );
- } catch (Exception e) {
- throw new RuntimeException("error reading or parsing jdeps file", IOUtils.getRootCause(e));
- }
-
- try {
- Path outputPath = Paths.get(output);
- Files.deleteIfExists(outputPath);
- try (FileOutputStream fileOutputStream = new FileOutputStream(Files.createFile(outputPath).toFile())) {
- jdepsContent.writeTo(fileOutputStream);
- }
- } catch (Exception e) {
- throw new RuntimeException("error writing out jdeps file", IOUtils.getRootCause(e));
- }
-
- return 0;
- }
-}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/GenerateJdepsFile.kt b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/GenerateJdepsFile.kt
new file mode 100644
index 0000000..120e38d
--- /dev/null
+++ b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/GenerateJdepsFile.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2018 The Bazel Authors. All rights reserved.
+ *
+ * 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
+ *
+ * http://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 io.bazel.ruleskotlin.workers.compilers.jvm.actions
+
+import com.google.devtools.build.lib.view.proto.Deps
+import io.bazel.ruleskotlin.workers.BuildAction
+import io.bazel.ruleskotlin.workers.Context
+import io.bazel.ruleskotlin.workers.Flags.*
+import io.bazel.ruleskotlin.workers.KotlinToolchain
+import io.bazel.ruleskotlin.workers.compilers.jvm.utils.JdepsParser
+import io.bazel.ruleskotlin.workers.utils.executeAndWaitOutput
+import io.bazel.ruleskotlin.workers.utils.rootCause
+import java.io.FileOutputStream
+import java.nio.file.Files
+import java.nio.file.Paths
+
+
+class GenerateJdepsFile(toolchain: KotlinToolchain) : BuildAction("generate jdeps", toolchain) {
+ private val isKotlinImplicit = JdepsParser.pathSuffixMatchingPredicate(toolchain.KOTLIN_LIB_DIR, *toolchain.KOTLIN_STD_LIBS)
+
+ override fun invoke(ctx: Context): Int {
+ val classJar = checkNotNull(OUTPUT_CLASSJAR[ctx])
+ val classPath = checkNotNull(CLASSPATH[ctx])
+ val output = checkNotNull(OUTPUT_JDEPS[ctx])
+ val label = checkNotNull(LABEL[ctx])
+ val jdepsContent: Deps.Dependencies
+
+ try {
+ jdepsContent = executeAndWaitOutput(10, toolchain.JDEPS_PATH, "-cp", classPath, classJar).let {
+ JdepsParser.parse(label, classJar, classPath, it.stream(), isKotlinImplicit)
+ }
+ } catch (e: Exception) {
+ throw RuntimeException("error reading or parsing jdeps file", e.rootCause)
+ }
+
+ try {
+ Paths.get(output).also {
+ Files.deleteIfExists(it)
+ FileOutputStream(Files.createFile(it).toFile()).use {
+ jdepsContent.writeTo(it)
+ }
+ }
+ } catch (e: Exception) {
+ throw RuntimeException("error writing out jdeps file", e.rootCause)
+ }
+ return 0
+ }
+}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/Initialize.java b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/Initialize.java
deleted file mode 100644
index 2e175bc..0000000
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/Initialize.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2018 The Bazel Authors. All rights reserved.
- *
- * 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
- *
- * http://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 io.bazel.ruleskotlin.workers.compilers.jvm.actions;
-
-
-import io.bazel.ruleskotlin.workers.BuildAction;
-import io.bazel.ruleskotlin.workers.Context;
-import io.bazel.ruleskotlin.workers.Flags;
-import io.bazel.ruleskotlin.workers.Meta;
-import io.bazel.ruleskotlin.workers.compilers.jvm.Metas;
-import io.bazel.ruleskotlin.workers.utils.IOUtils;
-
-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.Collections;
-import java.util.List;
-
-/**
- * Should be the first step, does mandatory pre-processing.
- */
-public final class Initialize implements BuildAction {
- public static final Initialize INSTANCE = new Initialize();
-
- private Initialize() {
- }
-
- @Override
- public Integer apply(Context ctx) {
- ctx.apply(
- Initialize::initializeAndBindBindDirectories,
- Initialize::bindLabelComponents,
- Initialize::bindSources
- );
- return 0;
- }
-
- private static void bindSources(Context ctx) {
- List<String> javaSources = new ArrayList<>();
- List<String> allSources = new ArrayList<>();
- for (String src : Flags.SOURCES.get(ctx).split(":")) {
- if (src.endsWith(".java")) {
- javaSources.add(src);
- allSources.add(src);
- } else if (src.endsWith(".kt")) {
- allSources.add(src);
- } else {
- throw new RuntimeException("unrecognised file type: " + src);
- }
- }
- Metas.JAVA_SOURCES.bind(ctx, Collections.unmodifiableList(javaSources));
- Metas.ALL_SOURCES.bind(ctx, Collections.unmodifiableList(allSources));
- }
-
- private static void initializeAndBindBindDirectories(Context ctx) {
- Path outputBase;
-
- try {
- outputBase = Files.createDirectories(Paths.get(Flags.COMPILER_OUTPUT_BASE.get(ctx)));
- } catch (IOException e) {
- throw new RuntimeException("could not create compiler output base", e);
- }
-
- try {
- IOUtils.purgeDirectory(outputBase);
- } catch (IOException e) {
- throw new RuntimeException("could not purge output directory", e);
- }
-
- createAndBindComponentDirectory(ctx, outputBase, Metas.CLASSES_DIRECTORY, "_classes");
- }
-
- private static void createAndBindComponentDirectory(Context ctx, Path outputBase, Meta<Path> key, String component) {
- try {
- key.bind(ctx, Files.createDirectories(outputBase.resolve(component)));
- } catch (IOException e) {
- throw new RuntimeException("could not create subdirectory for component " + component, e);
- }
- }
-
- /**
- * parses the label, sets up the meta elements and returns the target part.
- */
- private static void bindLabelComponents(Context ctx) {
- String label = Flags.LABEL.get(ctx);
- String[] parts = label.split(":");
- if (parts.length != 2) {
- throw new RuntimeException("the label " + label + " is invalid");
- }
- Metas.PKG.bind(ctx, parts[0]);
- Metas.TARGET.bind(ctx, parts[1]);
- }
-}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/Initialize.kt b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/Initialize.kt
new file mode 100644
index 0000000..6a3f3b9
--- /dev/null
+++ b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/Initialize.kt
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2018 The Bazel Authors. All rights reserved.
+ *
+ * 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
+ *
+ * http://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 io.bazel.ruleskotlin.workers.compilers.jvm.actions
+
+
+import io.bazel.ruleskotlin.workers.*
+import io.bazel.ruleskotlin.workers.compilers.jvm.Metas
+
+import io.bazel.ruleskotlin.workers.utils.purgeDirectory
+
+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.Collections
+
+/**
+ * Should be the first step, does mandatory pre-processing.
+ */
+class Initialize(toolchain: KotlinToolchain) : BuildAction("initialize KotlinBuilder", toolchain) {
+ override fun invoke(ctx: Context): Int {
+ ctx.apply(
+ ::initializeAndBindBindDirectories,
+ ::bindLabelComponents,
+ ::bindSources
+ )
+ return 0
+ }
+
+ private fun bindSources(ctx: Context) {
+ val javaSources = ArrayList<String>()
+ val allSources = ArrayList<String>()
+ for (src in requireNotNull(Flags.SOURCES[ctx]).split(":")) {
+ when {
+ src.endsWith(".java") -> {
+ javaSources.add(src)
+ allSources.add(src)
+ }
+ src.endsWith(".kt") -> allSources.add(src)
+ else -> throw RuntimeException("unrecognised file type: $src")
+ }
+ }
+ Metas.JAVA_SOURCES.bind(ctx, Collections.unmodifiableList(javaSources))
+ Metas.ALL_SOURCES.bind(ctx, Collections.unmodifiableList(allSources))
+ }
+
+ private fun initializeAndBindBindDirectories(ctx: Context) {
+ val outputBase: Path
+
+ try {
+ outputBase = Files.createDirectories(Paths.get(checkNotNull(Flags.COMPILER_OUTPUT_BASE[ctx])))
+ } catch (e: IOException) {
+ throw RuntimeException("could not create compiler output base", e)
+ }
+
+ try {
+ outputBase.purgeDirectory()
+ } catch (e: IOException) {
+ throw RuntimeException("could not purge output directory", e)
+ }
+
+ createAndBindComponentDirectory(ctx, outputBase, Metas.CLASSES_DIRECTORY, "_classes")
+ }
+
+ private fun createAndBindComponentDirectory(ctx: Context, outputBase: Path, key: Meta<Path>, component: String) {
+ try {
+ key.bind(ctx, Files.createDirectories(outputBase.resolve(component)))
+ } catch (e: IOException) {
+ throw RuntimeException("could not create subdirectory for component " + component, e)
+ }
+
+ }
+
+ /**
+ * parses the label, sets up the meta elements and returns the target part.
+ */
+ private fun bindLabelComponents(ctx: Context) {
+ val label = requireNotNull(Flags.LABEL[ctx])
+ val parts = label.split(":")
+ require(parts.size == 2) { "the label $label is invalid" }
+ Metas.PKG.bind(ctx, parts[0])
+ Metas.TARGET.bind(ctx, parts[1])
+ }
+}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/JavaMainCompile.java b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/JavaMainCompile.java
deleted file mode 100644
index da6da78..0000000
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/JavaMainCompile.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2018 The Bazel Authors. All rights reserved.
- *
- * 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
- *
- * http://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 io.bazel.ruleskotlin.workers.compilers.jvm.actions;
-
-import io.bazel.ruleskotlin.workers.BuildAction;
-import io.bazel.ruleskotlin.workers.Context;
-import io.bazel.ruleskotlin.workers.Flags;
-import io.bazel.ruleskotlin.workers.compilers.jvm.*;
-import io.bazel.ruleskotlin.workers.utils.IOUtils;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Simple java compile action that invokes javac directly and simply.
- */
-public final class JavaMainCompile implements BuildAction {
- private static final String JAVAC_PATH = Locations.JAVA_HOME.resolveVerified("bin", "javac").toString();
-
- public JavaMainCompile() {}
-
- @Override
- public Integer apply(Context ctx) {
- List<String> javaSources = Metas.JAVA_SOURCES.mustGet(ctx);
- if (!javaSources.isEmpty()) {
- List<String> args = new ArrayList<>();
- String classesDirectory = Metas.CLASSES_DIRECTORY.mustGet(ctx).toString();
- Collections.addAll(args,
- JAVAC_PATH, "-cp", classesDirectory + "/:" + Flags.CLASSPATH.get(ctx),
- "-d", classesDirectory
- );
- args.addAll(javaSources);
- Metas.JAVAC_RESULT.runAndBind(ctx, () -> IOUtils.executeAndAwait(30, args));
- }
- return 0;
- }
-}
-
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/JavaMainCompile.kt b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/JavaMainCompile.kt
new file mode 100644
index 0000000..3ae306b
--- /dev/null
+++ b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/JavaMainCompile.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2018 The Bazel Authors. All rights reserved.
+ *
+ * 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
+ *
+ * http://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 io.bazel.ruleskotlin.workers.compilers.jvm.actions
+
+import io.bazel.ruleskotlin.workers.BuildAction
+import io.bazel.ruleskotlin.workers.Context
+import io.bazel.ruleskotlin.workers.Flags
+import io.bazel.ruleskotlin.workers.KotlinToolchain
+import io.bazel.ruleskotlin.workers.compilers.jvm.Metas
+import io.bazel.ruleskotlin.workers.utils.executeAndAwait
+
+/**
+ * Simple java compile action that invokes javac directly and simply.
+ */
+class JavaMainCompile(toolchain: KotlinToolchain) : BuildAction("compile java classes", toolchain) {
+ override fun invoke(ctx: Context): Int {
+ val javaSources = Metas.JAVA_SOURCES.mustGet(ctx)
+ val classpath = checkNotNull(Flags.CLASSPATH[ctx])
+
+ if (!javaSources.isEmpty()) {
+ val classesDirectory = Metas.CLASSES_DIRECTORY.mustGet(ctx).toString()
+
+ val args = mutableListOf(toolchain.JAVAC_PATH, "-cp", "$classesDirectory/:$classpath", "-d", classesDirectory).also { it.addAll(javaSources) }
+ Metas.JAVAC_RESULT.runAndBind(ctx) { executeAndAwait(30, args) }
+ }
+ return 0
+ }
+}
+
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/KotlinMainCompile.java b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/KotlinMainCompile.java
deleted file mode 100644
index ad467fe..0000000
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/KotlinMainCompile.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2018 The Bazel Authors. All rights reserved.
- *
- * 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
- *
- * http://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 io.bazel.ruleskotlin.workers.compilers.jvm.actions;
-
-import io.bazel.ruleskotlin.workers.*;
-import io.bazel.ruleskotlin.workers.compilers.jvm.Metas;
-import io.bazel.ruleskotlin.workers.compilers.jvm.utils.KotlinCompilerOutputProcessor;
-
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Either compiles to a jar directly or when performing mixed-mode-compilation compiles to a temp directory first.
- * <p>
- * Mixed-Mode:
- * <p>
- * The Kotlin compiler is not suited for javac compilation as of 1.2.21. The errors are not conveyed directly and would need to be preprocessed, also javac
- * invocations Configured via Kotlin use eager analysis in some corner cases this can result in classpath exceptions from the Java Compiler..
- */
-public final class KotlinMainCompile implements BuildAction {
- private final KotlinToolchain.KotlinCompiler kotlinCompiler;
-
- public KotlinMainCompile(KotlinToolchain toolchains) {
- this.kotlinCompiler = toolchains.kotlinCompiler();
- }
-
- /**
- * Default fields that are directly mappable to kotlin compiler args.
- */
- private static final Flags[] COMPILE_MAPPED_FLAGS = new Flags[]{
- Flags.CLASSPATH,
- Flags.KOTLIN_API_VERSION,
- Flags.KOTLIN_LANGUAGE_VERSION,
- Flags.KOTLIN_JVM_TARGET
- };
-
- /**
- * Evaluate the compilation context and add Metadata to the ctx if needed.
- *
- * @return The args to pass to the kotlin compile class.
- */
- private static String[] setupCompileContext(Context ctx) {
- List<String> args = new ArrayList<>();
- Collections.addAll(args, "-d", Metas.CLASSES_DIRECTORY.mustGet(ctx).toString());
- ctx.of(COMPILE_MAPPED_FLAGS).forEach((field, arg) -> Collections.addAll(args, field.kotlinFlag, arg));
- args.addAll(Metas.ALL_SOURCES.mustGet(ctx));
- return args.toArray(new String[args.size()]);
- }
-
- @Override
- public Integer apply(Context ctx) {
- KotlinCompilerOutputProcessor outputProcessor;
- outputProcessor = new KotlinCompilerOutputProcessor.ForKotlinC(System.out);
-
- final Integer exitCode = kotlinCompiler.apply(setupCompileContext(ctx), outputProcessor.getCollector());
- if (exitCode < 2) {
- // 1 is a standard compilation error
- // 2 is an internal error
- // 3 is the script execution error
-
- // give javac a chance to process the java sources.
- Metas.KOTLINC_RESULT.bind(ctx, CompileResult.deferred(exitCode, (c) -> {
- outputProcessor.process();
- return exitCode;
- }));
- return 0;
- } else {
- outputProcessor.process();
- throw new RuntimeException("KotlinMainCompile returned terminal error code: " + exitCode);
- }
- }
-}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/KotlinMainCompile.kt b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/KotlinMainCompile.kt
new file mode 100644
index 0000000..bf5b1ab
--- /dev/null
+++ b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/KotlinMainCompile.kt
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2018 The Bazel Authors. All rights reserved.
+ *
+ * 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
+ *
+ * http://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 io.bazel.ruleskotlin.workers.compilers.jvm.actions
+
+import io.bazel.ruleskotlin.workers.*
+import io.bazel.ruleskotlin.workers.compilers.jvm.Metas
+import io.bazel.ruleskotlin.workers.compilers.jvm.utils.KotlinCompilerOutputProcessor
+
+
+import java.util.ArrayList
+import java.util.Collections
+
+/**
+ * Either compiles to a jar directly or when performing mixed-mode-compilation compiles to a temp directory first.
+ *
+ *
+ * Mixed-Mode:
+ *
+ *
+ * The Kotlin compiler is not suited for javac compilation as of 1.2.21. The errors are not conveyed directly and would need to be preprocessed, also javac
+ * invocations Configured via Kotlin use eager analysis in some corner cases this can result in classpath exceptions from the Java Compiler..
+ */
+class KotlinMainCompile(toolchain: KotlinToolchain) : BuildAction("compile kotlin classes", toolchain) {
+ companion object {
+ /**
+ * Default fields that are directly mappable to kotlin compiler args.
+ */
+ private val COMPILE_MAPPED_FLAGS = arrayOf(
+ Flags.CLASSPATH,
+ Flags.KOTLIN_API_VERSION,
+ Flags.KOTLIN_LANGUAGE_VERSION,
+ Flags.KOTLIN_JVM_TARGET)
+
+ /**
+ * Evaluate the compilation context and add Metadata to the ctx if needed.
+ *
+ * @return The args to pass to the kotlin compile class.
+ */
+ private fun setupCompileContext(ctx: Context): Array<String> {
+ val args = ArrayList<String>()
+ Collections.addAll(args, "-d", Metas.CLASSES_DIRECTORY.mustGet(ctx).toString())
+ ctx.of(*COMPILE_MAPPED_FLAGS).forEach { field, arg ->
+ args.add(field.kotlinFlag!!); args.add(arg)
+
+ }
+ args.addAll(Metas.ALL_SOURCES.mustGet(ctx))
+ return args.toTypedArray()
+ }
+ }
+
+ override fun invoke(ctx: Context): Int {
+ val outputProcessor = KotlinCompilerOutputProcessor.ForKotlinC(System.out)
+
+ val exitCode = try {
+ toolchain.kotlinCompiler.compile(setupCompileContext(ctx), outputProcessor.collector)
+ } catch (ex: Exception) {
+ outputProcessor.process()
+ throw ex
+ }
+
+ if (exitCode < 2) {
+ // 1 is a standard compilation error
+ // 2 is an internal error
+ // 3 is the script execution error
+
+ // give javac a chance to process the java sources.
+ Metas.KOTLINC_RESULT.bind(ctx, CompileResult.deferred(exitCode) { _ ->
+ outputProcessor.process()
+ exitCode
+ })
+ return 0
+ } else {
+ outputProcessor.process()
+ throw RuntimeException("KotlinMainCompile returned terminal error code: $exitCode")
+ }
+ }
+}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/KotlinRenderClassCompileResult.java b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/KotlinRenderClassCompileResult.java
deleted file mode 100644
index 76c8674..0000000
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/KotlinRenderClassCompileResult.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2018 The Bazel Authors. All rights reserved.
- *
- * 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
- *
- * http://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 io.bazel.ruleskotlin.workers.compilers.jvm.actions;
-
-
-import io.bazel.ruleskotlin.workers.BuildAction;
-import io.bazel.ruleskotlin.workers.CompileResult;
-import io.bazel.ruleskotlin.workers.Context;
-import io.bazel.ruleskotlin.workers.compilers.jvm.Metas;
-
-import java.util.Optional;
-
-
-/**
- * Render the result of class compilation. This is a separate step at the moment for mixed mode compilation scenarios. If there is an error in Java sources in
- * a large mixed mode package the Kotlin errors don't make any sense and overwhelm the console and intellij. The {@link KotlinMainCompile} step binds a deferred
- * renderer and proceeds to lets javac compile the java sources. The step below merges the result of the two actions.
- */
-public final class KotlinRenderClassCompileResult implements BuildAction {
- public static final KotlinRenderClassCompileResult INSTANCE = new KotlinRenderClassCompileResult();
-
- private KotlinRenderClassCompileResult() {
- }
-
- @Override
- public Integer apply(Context ctx) {
- CompileResult kotlincResult = Metas.KOTLINC_RESULT.mustGet(ctx);
- Optional<CompileResult> javacResult = Metas.JAVAC_RESULT.get(ctx);
- if (!javacResult.isPresent()) {
- return kotlincResult.render(ctx);
- } else {
- try {
- javacResult.get().propogateError("javac failed");
- if (kotlincResult.status() != 0) {
- return kotlincResult.status();
- } else if (javacResult.get().status() != 0) {
- // treat all javac statuses as non terminal compile errors.
- return 1;
- }
- return 0;
- } finally {
- kotlincResult.render(ctx);
- }
- }
- }
-}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/ProcessCompileResult.kt b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/ProcessCompileResult.kt
new file mode 100644
index 0000000..01fbf3b
--- /dev/null
+++ b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/ProcessCompileResult.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2018 The Bazel Authors. All rights reserved.
+ *
+ * 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
+ *
+ * http://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 io.bazel.ruleskotlin.workers.compilers.jvm.actions
+
+
+import io.bazel.ruleskotlin.workers.BuildAction
+import io.bazel.ruleskotlin.workers.Context
+import io.bazel.ruleskotlin.workers.KotlinToolchain
+import io.bazel.ruleskotlin.workers.compilers.jvm.Metas
+
+
+/**
+ * Render the result of class compilation. This is a separate step at the moment for mixed mode compilation scenarios. If there is an error in Java sources in
+ * a large mixed mode package the Kotlin errors don't make any sense and overwhelm the console and intellij. The [KotlinMainCompile] step binds a deferred
+ * renderer and proceeds to lets javac compile the java sources. The step below merges the result of the two actions.
+ */
+class ProcessCompileResult(toolchain: KotlinToolchain) : BuildAction("render class compile output", toolchain) {
+ override fun invoke(ctx: Context): Int {
+ val kotlincResult = Metas.KOTLINC_RESULT.mustGet(ctx)
+ val javacResult = Metas.JAVAC_RESULT[ctx]
+
+ return if (javacResult == null) {
+ kotlincResult.render(ctx)
+ } else {
+ try {
+ javacResult.propogateError("javac failed")
+ if (kotlincResult.status() != 0) {
+ return kotlincResult.status()
+ } else if (javacResult.status() != 0) {
+ // treat all javac statuses as non terminal compile errors.
+ return 1
+ }
+ 0
+ } finally {
+ kotlincResult.render(ctx)
+ }
+ }
+ }
+}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/utils/JdepsParser.java b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/utils/JdepsParser.java
deleted file mode 100644
index 9d705b8..0000000
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/utils/JdepsParser.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright 2018 The Bazel Authors. All rights reserved.
- *
- * 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
- *
- * http://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 io.bazel.ruleskotlin.workers.compilers.jvm.utils;
-
-import com.google.devtools.build.lib.view.proto.Deps;
-
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.Predicate;
-import java.util.stream.Stream;
-
-public class JdepsParser {
- private final String filename;
- private final String packageSuffix;
- private final Predicate<String> isImplicit;
-
- private final Map<String, Deps.Dependency.Builder> depMap = new HashMap<>();
- private final Set<String> packages = new HashSet<>();
-
- private JdepsParser(String filename, Predicate<String> isImplicit) {
- this.filename = filename;
- this.packageSuffix = " (" + filename + ")";
- this.isImplicit = isImplicit;
- }
-
- private void consumeJarLine(String classJarPath, Deps.Dependency.Kind kind) {
- Path path = Paths.get(classJarPath);
-
- // ignore absolute files, -- jdk jar paths etc.
- // only process jar files
- if (!(path.isAbsolute() || !classJarPath.endsWith(".jar"))) {
- Deps.Dependency.Builder entry = depMap.computeIfAbsent(classJarPath, (key) -> {
- Deps.Dependency.Builder depBuilder = Deps.Dependency.newBuilder();
- depBuilder.setPath(classJarPath);
- depBuilder.setKind(kind);
-
- if (isImplicit.test(classJarPath)) {
- depBuilder.setKind(Deps.Dependency.Kind.IMPLICIT);
- }
- return depBuilder;
- });
-
- // don't flip an implicit dep.
- if (entry.getKind() != Deps.Dependency.Kind.IMPLICIT) {
- entry.setKind(kind);
- }
- }
- }
-
- private enum Mode {
- COLLECT_DEPS,
- DETERMINE_JDK,
- COLLECT_PACKAGES_JDK8,
- COLLECT_PACKAGES_JDK9
- }
-
- private Mode mode = Mode.COLLECT_DEPS;
-
- // maybe simplify this by tokenizing on whitespace and arrows.
- private void processLine(String line) {
- String trimmedLine = line.trim();
- switch (mode) {
- case COLLECT_DEPS:
- if (!line.startsWith(" ")) {
- String[] parts = line.split(" -> ");
- if (parts.length == 2) {
- if (!parts[0].equals(filename)) {
- throw new RuntimeException("should only get dependencies for dep: " + filename);
- }
- consumeJarLine(parts[1], Deps.Dependency.Kind.EXPLICIT);
- }
- } else {
- mode = Mode.DETERMINE_JDK;
- processLine(line);
- }
- break;
- case DETERMINE_JDK:
- mode = Mode.COLLECT_PACKAGES_JDK8;
- if (!line.endsWith(packageSuffix)) {
- mode = Mode.COLLECT_PACKAGES_JDK9;
- }
- processLine(line);
- break;
- case COLLECT_PACKAGES_JDK8:
- if (trimmedLine.endsWith(packageSuffix)) {
- packages.add(trimmedLine.substring(0, trimmedLine.length() - packageSuffix.length()));
- } else if (trimmedLine.startsWith("-> ")) {
- // ignore package detail lines, in the jdk8 format these start with arrows.
- } else throw new RuntimeException("unexpected line while collecting packages: " + line);
- break;
- case COLLECT_PACKAGES_JDK9:
- String[] pkg = trimmedLine.split("\\s+");
- packages.add(pkg[0]);
- break;
- }
- }
-
-
- public static Predicate<String> pathSuffixMatchingPredicate(Path directory, String... jars) {
- String[] suffixes = Stream.of(jars).map(lib -> directory.resolve(lib).toString()).toArray(String[]::new);
- return (jar) -> {
- for (String implicitJarsEnding : suffixes) {
- if (jar.endsWith(implicitJarsEnding)) {
- return true;
- }
- }
- return false;
- };
- }
-
- public static Deps.Dependencies parse(String label, String classJar, String classPath, Stream<String> jdepLines, Predicate<String> isImplicit) {
- String filename = Paths.get(classJar).getFileName().toString();
- JdepsParser jdepsParser = new JdepsParser(filename, isImplicit);
- Stream.of(classPath.split(":")).forEach(x -> jdepsParser.consumeJarLine(x, Deps.Dependency.Kind.UNUSED));
- jdepLines.forEach(jdepsParser::processLine);
-
- Deps.Dependencies.Builder rootBuilder = Deps.Dependencies.newBuilder();
- rootBuilder.setSuccess(false);
- rootBuilder.setRuleLabel(label);
-
- rootBuilder.addAllContainedPackage(jdepsParser.packages);
- jdepsParser.depMap.values().forEach(b -> rootBuilder.addDependency(b.build()));
-
- rootBuilder.setSuccess(true);
- return rootBuilder.build();
- }
-}
\ No newline at end of file
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/utils/JdepsParser.kt b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/utils/JdepsParser.kt
new file mode 100644
index 0000000..dc835dd
--- /dev/null
+++ b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/utils/JdepsParser.kt
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2018 The Bazel Authors. All rights reserved.
+ *
+ * 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
+ *
+ * http://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 io.bazel.ruleskotlin.workers.compilers.jvm.utils
+
+import com.google.devtools.build.lib.view.proto.Deps
+import java.nio.file.Path
+import java.nio.file.Paths
+import java.util.*
+import java.util.function.Predicate
+import java.util.stream.Stream
+
+class JdepsParser private constructor(private val filename: String, private val isImplicit: Predicate<String>) {
+ private val packageSuffix: String = " ($filename)"
+
+ private val depMap = HashMap<String, Deps.Dependency.Builder>()
+ private val packages = HashSet<String>()
+
+ private var mode = Mode.COLLECT_DEPS
+
+ private fun consumeJarLine(classJarPath: String, kind: Deps.Dependency.Kind) {
+ val path = Paths.get(classJarPath)
+
+ // ignore absolute files, -- jdk jar paths etc.
+ // only process jar files
+ if (!(path.isAbsolute || !classJarPath.endsWith(".jar"))) {
+ val entry = depMap.computeIfAbsent(classJarPath) {
+ val depBuilder = Deps.Dependency.newBuilder()
+ depBuilder.path = classJarPath
+ depBuilder.kind = kind
+
+ if (isImplicit.test(classJarPath)) {
+ depBuilder.kind = Deps.Dependency.Kind.IMPLICIT
+ }
+ depBuilder
+ }
+
+ // don't flip an implicit dep.
+ if (entry.kind != Deps.Dependency.Kind.IMPLICIT) {
+ entry.kind = kind
+ }
+ }
+ }
+
+ private enum class Mode {
+ COLLECT_DEPS,
+ DETERMINE_JDK,
+ COLLECT_PACKAGES_JDK8,
+ COLLECT_PACKAGES_JDK9
+ }
+
+ // maybe simplify this by tokenizing on whitespace and arrows.
+ private fun processLine(line: String) {
+ val trimmedLine = line.trim { it <= ' ' }
+ when (mode) {
+ JdepsParser.Mode.COLLECT_DEPS -> if (!line.startsWith(" ")) {
+ val parts = line.split(" -> ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
+ if (parts.size == 2) {
+ if (parts[0] != filename) {
+ throw RuntimeException("should only get dependencies for dep: " + filename)
+ }
+ consumeJarLine(parts[1], Deps.Dependency.Kind.EXPLICIT)
+ }
+ } else {
+ mode = Mode.DETERMINE_JDK
+ processLine(line)
+ }
+ JdepsParser.Mode.DETERMINE_JDK -> {
+ mode = Mode.COLLECT_PACKAGES_JDK8
+ if (!line.endsWith(packageSuffix)) {
+ mode = Mode.COLLECT_PACKAGES_JDK9
+ }
+ processLine(line)
+ }
+ JdepsParser.Mode.COLLECT_PACKAGES_JDK8 -> when {
+ trimmedLine.endsWith(packageSuffix) -> packages.add(trimmedLine.substring(0, trimmedLine.length - packageSuffix.length))
+ trimmedLine.startsWith("-> ") -> {
+ // ignore package detail lines, in the jdk8 format these start with arrows.
+ }
+ else -> throw RuntimeException("unexpected line while collecting packages: " + line)
+ }
+ JdepsParser.Mode.COLLECT_PACKAGES_JDK9 -> {
+ val pkg = trimmedLine.split("\\s+".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
+ packages.add(pkg[0])
+ }
+ }
+ }
+
+ companion object {
+ fun pathSuffixMatchingPredicate(directory: Path, vararg jars: String): Predicate<String> {
+ val suffixes = jars.map { directory.resolve(it).toString() }
+ return Predicate { jar ->
+ for (implicitJarsEnding in suffixes) {
+ if (jar.endsWith(implicitJarsEnding)) {
+ return@Predicate true
+ }
+ }
+ false
+ }
+ }
+
+ fun parse(label: String, classJar: String, classPath: String, jdepLines: Stream<String>, isImplicit: Predicate<String>): Deps.Dependencies {
+ val filename = Paths.get(classJar).fileName.toString()
+ val jdepsParser = JdepsParser(filename, isImplicit)
+ Stream.of(*classPath.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()).forEach { x -> jdepsParser.consumeJarLine(x, Deps.Dependency.Kind.UNUSED) }
+ jdepLines.forEach { jdepsParser.processLine(it) }
+
+ val rootBuilder = Deps.Dependencies.newBuilder()
+ rootBuilder.success = false
+ rootBuilder.ruleLabel = label
+
+ rootBuilder.addAllContainedPackage(jdepsParser.packages)
+ jdepsParser.depMap.values.forEach { b -> rootBuilder.addDependency(b.build()) }
+
+ rootBuilder.success = true
+ return rootBuilder.build()
+ }
+ }
+}
\ No newline at end of file
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/utils/KotlinCompilerOutputProcessor.java b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/utils/KotlinCompilerOutputProcessor.java
deleted file mode 100644
index f40d071..0000000
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/utils/KotlinCompilerOutputProcessor.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2018 The Bazel Authors. All rights reserved.
- *
- * 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
- *
- * http://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 io.bazel.ruleskotlin.workers.compilers.jvm.utils;
-
-import java.io.*;
-import java.nio.file.Paths;
-import java.util.stream.Collectors;
-
-
-/**
- * Utility class to perform common pre-processing on the compiler output before it is passed onto a delegate
- * PrintStream.
- */
-// The kotlin compiler produces absolute file paths but the intellij plugin expects workspace root relative paths to
-// render errors.
-public abstract class KotlinCompilerOutputProcessor {
- private final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
- // Get the absolute path to ensure the sandbox root is resolved.
- private final String executionRoot = Paths.get("").toAbsolutePath().toString() + File.separator;
- final PrintStream delegate;
-
- private KotlinCompilerOutputProcessor(PrintStream delegate) {
- this.delegate = delegate;
- }
-
- public PrintStream getCollector() {
- return new PrintStream(byteArrayOutputStream);
- }
-
- public static class ForKotlinC extends KotlinCompilerOutputProcessor {
- public ForKotlinC(PrintStream delegate) {
- super(delegate);
- }
-
- @Override
- protected boolean processLine(String line) {
- delegate.println(trimExecutionRootPrefix(line));
- return true;
- }
- }
-
-
- final String trimExecutionRootPrefix(String toPrint) {
- // trim off the workspace component
- if (toPrint.startsWith(executionRoot)) {
- return toPrint.replaceFirst(executionRoot, "");
- }
- return toPrint;
- }
-
- protected abstract boolean processLine(String line);
-
- public void process() {
- for (String s : new BufferedReader(new InputStreamReader(new ByteArrayInputStream(byteArrayOutputStream.toByteArray())))
- .lines().collect(Collectors.toList())) {
- boolean shouldContinue = processLine(s);
- if(!shouldContinue) {
- break;
- }
- }
- delegate.flush();
- }
-}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/utils/KotlinCompilerOutputProcessor.kt b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/utils/KotlinCompilerOutputProcessor.kt
new file mode 100644
index 0000000..899fbc8
--- /dev/null
+++ b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/utils/KotlinCompilerOutputProcessor.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2018 The Bazel Authors. All rights reserved.
+ *
+ * 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
+ *
+ * http://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 io.bazel.ruleskotlin.workers.compilers.jvm.utils
+
+import java.io.ByteArrayInputStream
+import java.io.ByteArrayOutputStream
+import java.io.File
+import java.io.PrintStream
+import java.nio.file.Paths
+
+
+/**
+ * Utility class to perform common pre-processing on the compiler output before it is passed onto a delegate
+ * PrintStream.
+ */
+// The kotlin compiler produces absolute file paths but the intellij plugin expects workspace root relative paths to
+// render errors.
+abstract class KotlinCompilerOutputProcessor private constructor(internal val delegate: PrintStream) {
+ private val byteArrayOutputStream = ByteArrayOutputStream()
+ // Get the absolute path to ensure the sandbox root is resolved.
+ private val executionRoot = Paths.get("").toAbsolutePath().toString() + File.separator
+
+ val collector: PrintStream = PrintStream(byteArrayOutputStream)
+
+ class ForKotlinC(delegate: PrintStream) : KotlinCompilerOutputProcessor(delegate) {
+ override fun processLine(line: String): Boolean {
+ delegate.println(trimExecutionRootPrefix(line))
+ return true
+ }
+ }
+
+ internal fun trimExecutionRootPrefix(toPrint: String): String {
+ // trim off the workspace component
+ return if (toPrint.startsWith(executionRoot)) {
+ toPrint.replaceFirst(executionRoot.toRegex(), "")
+ } else toPrint
+ }
+
+ protected abstract fun processLine(line: String): Boolean
+
+ fun process() {
+ try {
+ for (s in ByteArrayInputStream(byteArrayOutputStream.toByteArray()).bufferedReader().lineSequence()) {
+ val shouldContinue = processLine(s)
+ if (!shouldContinue) {
+ break
+ }
+ }
+ } finally {
+ delegate.flush()
+ }
+ }
+}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/utils/IOUtils.java b/kotlin/workers/src/io/bazel/ruleskotlin/workers/utils/IOUtils.java
deleted file mode 100644
index d4e83eb..0000000
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/utils/IOUtils.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright 2018 The Bazel Authors. All rights reserved.
- *
- * 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
- *
- * http://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 io.bazel.ruleskotlin.workers.utils;
-
-import java.io.*;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-public final class IOUtils {
- // sort this one out
- public static List<String> executeAndWaitOutput(int timeoutSeconds, String... command) {
- try {
- ProcessBuilder builder = new ProcessBuilder(command).redirectError(ProcessBuilder.Redirect.INHERIT);
- Process process = builder.start();
- ArrayList<String> al = new ArrayList<>();
- CompletableFuture<Void> streamReader = null;
- try (BufferedReader output = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
- streamReader = CompletableFuture.runAsync(() -> {
- while (true) {
- try {
- String line = output.readLine();
- if (line == null)
- break;
- al.add(line);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
- });
- executeAwait(timeoutSeconds, process);
- return al;
- } finally {
- if (streamReader != null && !streamReader.isDone()) {
- streamReader.cancel(true);
- }
- }
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- private static int executeAwait(int timeoutSeconds, Process process) throws TimeoutException {
- try {
- if (!process.waitFor(timeoutSeconds, TimeUnit.SECONDS)) {
- throw new TimeoutException();
- }
- return process.exitValue();
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- } finally {
- if (process.isAlive()) {
- process.destroy();
- }
- }
- }
-
- public static int executeAndAwait(int timeoutSeconds, List<String> args) {
- BufferedReader is = null;
- BufferedReader es = null;
- try {
- ProcessBuilder builder = new ProcessBuilder(args.toArray(new String[args.size()]));
- builder.redirectInput(ProcessBuilder.Redirect.PIPE);
- builder.redirectError(ProcessBuilder.Redirect.PIPE);
- Process process = builder.start();
- is = new BufferedReader(new InputStreamReader(process.getInputStream()));
- es = new BufferedReader(new InputStreamReader(process.getErrorStream()));
- return executeAwait(timeoutSeconds, process);
- } catch (Exception e) {
- throw new RuntimeException(e);
- } finally {
- drainStreamTo(System.out, is);
- drainStreamTo(System.err, es);
- }
- }
-
- private static void drainStreamTo(PrintStream writer, BufferedReader reader) {
- if (reader != null) {
- reader.lines().forEach(writer::println);
- try {
- reader.close();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
- }
-
- public static void executeAndAwaitSuccess(int timeoutSeconds, List<String> command) {
- int status = executeAndAwait(timeoutSeconds, command);
- if (status != 0) {
- throw new RuntimeException("process failed with status: " + status);
- }
- }
-
-
- public static void purgeDirectory(Path directory) throws IOException {
- File directoryAsFile = directory.toFile();
- Files.walk(directory)
- .map(Path::toFile)
- .sorted((o1, o2) -> -o1.compareTo(o2))
- .filter(file -> !directoryAsFile.equals(file)) // nasty
- .forEach(file -> {
- assert !file.delete();
- });
- }
-
- public static Throwable getRootCause(Throwable e) {
- Throwable cause;
- Throwable result = e;
-
- while (null != (cause = result.getCause()) && (result != cause)) {
- result = cause;
- }
- return result;
- }
-}
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/utils/IOUtils.kt b/kotlin/workers/src/io/bazel/ruleskotlin/workers/utils/IOUtils.kt
new file mode 100644
index 0000000..f743403
--- /dev/null
+++ b/kotlin/workers/src/io/bazel/ruleskotlin/workers/utils/IOUtils.kt
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2018 The Bazel Authors. All rights reserved.
+ *
+ * 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
+ *
+ * http://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.
+ */
+@file:JvmName("IOUtils")
+
+package io.bazel.ruleskotlin.workers.utils
+
+import java.io.*
+import java.nio.file.Path
+import java.nio.file.Paths
+import java.util.*
+import java.util.concurrent.CompletableFuture
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.TimeoutException
+
+fun executeAndWaitOutput(timeoutSeconds: Int, vararg command: String): List<String> {
+ try {
+ val builder = ProcessBuilder(*command).redirectError(ProcessBuilder.Redirect.INHERIT)
+ val process = builder.start()
+ val al = ArrayList<String>()
+ var streamReader: CompletableFuture<Void>? = null
+ try {
+ BufferedReader(InputStreamReader(process.inputStream)).use { output ->
+ streamReader = CompletableFuture.runAsync {
+ while (true) {
+ try {
+ val line = output.readLine() ?: break
+ al.add(line)
+ } catch (e: IOException) {
+ throw UncheckedIOException(e)
+ }
+
+ }
+ }
+ executeAwait(timeoutSeconds, process)
+ return al
+ }
+ } finally {
+ if (streamReader != null && !streamReader!!.isDone) {
+ streamReader!!.cancel(true)
+ }
+ }
+ } catch (e: Exception) {
+ throw RuntimeException(e)
+ }
+}
+
+private fun executeAwait(timeoutSeconds: Int, process: Process): Int {
+ try {
+ if (!process.waitFor(timeoutSeconds.toLong(), TimeUnit.SECONDS)) {
+ throw TimeoutException()
+ }
+ return process.exitValue()
+ } finally {
+ if (process.isAlive) {
+ process.destroy()
+ }
+ }
+}
+
+fun executeAndAwait(timeoutSeconds: Int, args: List<String>): Int {
+ val process = ProcessBuilder(*args.toTypedArray()).let {
+ it.redirectError(ProcessBuilder.Redirect.PIPE)
+ it.redirectOutput(ProcessBuilder.Redirect.PIPE)
+ it.start()
+ }
+
+ var isr: BufferedReader? = null
+ var esr: BufferedReader? = null
+
+ try {
+ isr = process.inputStream.bufferedReader()
+ esr = process.errorStream.bufferedReader()
+ return executeAwait(timeoutSeconds, process)
+ } finally {
+ isr?.drainTo(System.out)
+ esr?.drainTo(System.err)
+ }
+}
+
+fun executeAndAwaitSuccess(timeoutSeconds: Int, vararg command: String) {
+ val status = executeAndAwait(timeoutSeconds, command.toList())
+ check(status == 0) {
+ "process failed with status: $status"
+ }
+}
+
+private fun BufferedReader.drainTo(pw: PrintStream) {
+ lines().forEach(pw::println); close()
+}
+
+fun Path.purgeDirectory() {
+ toFile().listFiles().forEach { check(it.deleteRecursively()) { "$it could not be deleted" } }
+}
+
+fun Path.resolveVerified(vararg parts: String): File = resolve(Paths.get(parts[0], *Arrays.copyOfRange(parts, 1, parts.size))).verified()
+
+/**
+ * Return a stream of paths that are known to exists relative to this location.
+ */
+fun Path.verifiedRelativeFiles(vararg paths: Path): List<File> = paths.map { relative -> resolve(relative).verified() }
+
+private fun Path.verified(): File = this.toFile().also { check(it.exists()) { "file did not exist: $this" } }
+
+
+val Throwable.rootCause: Throwable
+ get() {
+ var result = this
+ do {
+ val cause = result.cause
+ if (cause != null) result = cause
+ } while (cause != null && result != cause)
+ return result
+ }
diff --git a/kotlin/workers/unittests/io/bazel/ruleskotlin/workers/compilers/jvm/utils/JdepsParserTest.java b/kotlin/workers/unittests/io/bazel/ruleskotlin/workers/compilers/jvm/utils/JdepsParserTest.java
index b61377c..ec49d86 100644
--- a/kotlin/workers/unittests/io/bazel/ruleskotlin/workers/compilers/jvm/utils/JdepsParserTest.java
+++ b/kotlin/workers/unittests/io/bazel/ruleskotlin/workers/compilers/jvm/utils/JdepsParserTest.java
@@ -89,7 +89,7 @@
private static final String LABEL = "//cloud/qa/integrationtests/pkg/alt";
private static final String CLASS_JAR = "bazel-bin/something/alt.jar";
- private static final Predicate<String> IS_KOTLIN_IMPLICIT = JdepsParser.pathSuffixMatchingPredicate(
+ private static final Predicate<String> IS_KOTLIN_IMPLICIT = JdepsParser.Companion.pathSuffixMatchingPredicate(
Paths.get("external", "com_github_jetbrains_kotlin", "lib"),
"kotlin-stdlib.jar",
"kotlin-stdlib-jdk7.jar",
@@ -106,7 +106,7 @@
}
private void testWithFixture(String fixture) throws IOException {
- Deps.Dependencies result = JdepsParser.parse(LABEL, CLASS_JAR, CLASSPATH.stream().collect(Collectors.joining(":")), Stream.of(fixture.split("\n")), IS_KOTLIN_IMPLICIT);
+ Deps.Dependencies result = JdepsParser.Companion.parse(LABEL, CLASS_JAR, CLASSPATH.stream().collect(Collectors.joining(":")), Stream.of(fixture.split("\n")), IS_KOTLIN_IMPLICIT);
Assert.assertEquals(LABEL, result.getRuleLabel());
Assert.assertEquals(7, result.getDependencyCount());