diff --git a/examples/trivial/.editorconfig b/examples/trivial/.editorconfig new file mode 100644 index 000000000..3e57cd27b --- /dev/null +++ b/examples/trivial/.editorconfig @@ -0,0 +1,6 @@ +[*.{kt, kts}] +indent_size = 2 +insert_final_newline = true +max_line_length = 100 +ij_kotlin_allow_trailing_comma = true +ij_kotlin_allow_trailing_comma_on_call_site = true diff --git a/examples/trivial/BUILD b/examples/trivial/BUILD index 104f2574f..1092070b5 100644 --- a/examples/trivial/BUILD +++ b/examples/trivial/BUILD @@ -1,4 +1,5 @@ load("@rules_java//java:defs.bzl", "java_library") +load("@rules_kotlin//kotlin:lint.bzl", "ktlint_config") package(default_visibility = ["//visibility:public"]) @@ -13,3 +14,16 @@ java_library( "@maven//:org_opentest4j_opentest4j", ], ) + +filegroup( + name = "editorconfig", + srcs = [".editorconfig"], +) + +ktlint_config( + name = "ktlint_editorconfig", + android_rules_enabled = False, + editorconfig = "//:editorconfig", + experimental_rules_enabled = False, + visibility = ["//visibility:public"], +) diff --git a/examples/trivial/app/App.kt b/examples/trivial/app/App.kt index 99e95b543..3a7311da6 100644 --- a/examples/trivial/app/App.kt +++ b/examples/trivial/app/App.kt @@ -5,21 +5,28 @@ import com.expedia.graphql.TopLevelObject import com.expedia.graphql.toSchema import graphql.GraphQL -data class Foo(val name: String, val age: Int) +data class Foo( + val name: String, + val age: Int, +) class Query { - fun foo(bar: String?) = Foo("$bar!", 42) + fun foo(bar: String?) = Foo("$bar!", 42) } class MyApp { - companion object { - @JvmStatic - fun main(args: Array) { - val schema = toSchema(queries = listOf(TopLevelObject(Query())), config = SchemaGeneratorConfig(listOf("app"))) - val graphql = GraphQL.newGraphQL(schema).build() - val result = graphql.execute("""{ foo(bar: "baz") { name, age } }""").toSpecification() + companion object { + @JvmStatic + fun main(args: Array) { + val schema = + toSchema( + queries = listOf(TopLevelObject(Query())), + config = SchemaGeneratorConfig(listOf("app")), + ) + val graphql = GraphQL.newGraphQL(schema).build() + val result = graphql.execute("""{ foo(bar: "baz") { name, age } }""").toSpecification() - println(result) - } + println(result) } + } } diff --git a/examples/trivial/app/BUILD.bazel b/examples/trivial/app/BUILD.bazel index 974052298..2a53326c1 100644 --- a/examples/trivial/app/BUILD.bazel +++ b/examples/trivial/app/BUILD.bazel @@ -13,11 +13,13 @@ kt_jvm_library( ktlint_test( name = "lint_test", srcs = glob(["**/*.kt"]), + config = "//:ktlint_editorconfig", ) ktlint_fix( name = "lint_fix", srcs = glob(["**/*.kt"]), + config = "//:ktlint_editorconfig", ) java_binary( diff --git a/src/main/kotlin/io/bazel/kotlin/builder/cmd/Build.kt b/src/main/kotlin/io/bazel/kotlin/builder/cmd/Build.kt index 8dd1911ab..227ae07c7 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/cmd/Build.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/cmd/Build.kt @@ -34,7 +34,6 @@ object Build { .build() .work(), ) - } - .run(::exitProcess) + }.run(::exitProcess) } } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/cmd/MergeJdeps.kt b/src/main/kotlin/io/bazel/kotlin/builder/cmd/MergeJdeps.kt index 4e81b9fb9..cb108f1d7 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/cmd/MergeJdeps.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/cmd/MergeJdeps.kt @@ -27,7 +27,6 @@ object MergeJdeps { Worker .from(args.toList()) { start(DaggerJdepsMergerComponent.builder().build().work()) - } - .run(::exitProcess) + }.run(::exitProcess) } } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/CompileKotlin.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/CompileKotlin.kt index a6a34aa4d..d800672f0 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/CompileKotlin.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/CompileKotlin.kt @@ -22,12 +22,18 @@ import io.bazel.worker.Work import io.bazel.worker.WorkerContext import javax.inject.Inject -class CompileKotlin @Inject constructor(private val builder: KotlinBuilder) : Work { - override fun invoke(ctx: WorkerContext.TaskContext, args: Iterable): Status { - return if (builder.build(ctx, args.toList()) != 0) { - Status.ERROR - } else { - Status.SUCCESS - } +class CompileKotlin + @Inject + constructor( + private val builder: KotlinBuilder, + ) : Work { + override fun invoke( + ctx: WorkerContext.TaskContext, + args: Iterable, + ): Status = + if (builder.build(ctx, args.toList()) != 0) { + Status.ERROR + } else { + Status.SUCCESS + } } -} diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt index d2dd9d483..d94cd4e3c 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/KotlinBuilder.kt @@ -41,283 +41,305 @@ import javax.inject.Singleton @Singleton @Suppress("MemberVisibilityCanBePrivate") -class KotlinBuilder @Inject internal constructor( - private val jvmTaskExecutor: KotlinJvmTaskExecutor, - private val jsTaskExecutor: Kotlin2JsTaskExecutor, -) { - companion object { - @JvmStatic - private val FLAGFILE_RE = Pattern.compile("""^--flagfile=((.*)-(\d+).params)$""").toRegex() +class KotlinBuilder + @Inject + internal constructor( + private val jvmTaskExecutor: KotlinJvmTaskExecutor, + private val jsTaskExecutor: Kotlin2JsTaskExecutor, + ) { + companion object { + @JvmStatic + private val FLAGFILE_RE = Pattern.compile("""^--flagfile=((.*)-(\d+).params)$""").toRegex() - enum class KotlinBuilderFlags(override val flag: String) : Flag { - TARGET_LABEL("--target_label"), - CLASSPATH("--classpath"), - DIRECT_DEPENDENCIES("--direct_dependencies"), - DEPS_ARTIFACTS("--deps_artifacts"), - SOURCES("--sources"), - SOURCE_JARS("--source_jars"), - PROCESSOR_PATH("--processorpath"), - PROCESSORS("--processors"), - STUBS_PLUGIN_OPTIONS("--stubs_plugin_options"), - STUBS_PLUGIN_CLASS_PATH("--stubs_plugin_classpath"), - COMPILER_PLUGIN_OPTIONS("--compiler_plugin_options"), - COMPILER_PLUGIN_CLASS_PATH("--compiler_plugin_classpath"), - OUTPUT("--output"), - RULE_KIND("--rule_kind"), - MODULE_NAME("--kotlin_module_name"), - PASSTHROUGH_FLAGS("--kotlin_passthrough_flags"), - API_VERSION("--kotlin_api_version"), - LANGUAGE_VERSION("--kotlin_language_version"), - JVM_TARGET("--kotlin_jvm_target"), - OUTPUT_SRCJAR("--kotlin_output_srcjar"), - GENERATED_CLASSDIR("--kotlin_generated_classdir"), - FRIEND_PATHS("--kotlin_friend_paths"), - OUTPUT_JDEPS("--kotlin_output_jdeps"), - OUTPUT_JS_JAR("--kotlin_output_js_jar"), - JS_PASSTHROUGH_FLAGS("--kotlin_js_passthrough_flags"), - JS_LIBRARIES("--kotlin_js_libraries"), - DEBUG("--kotlin_debug_tags"), - TASK_ID("--kotlin_task_id"), - ABI_JAR("--abi_jar"), - GENERATED_JAVA_SRC_JAR("--generated_java_srcjar"), - GENERATED_JAVA_STUB_JAR("--kapt_generated_stub_jar"), - GENERATED_CLASS_JAR("--kapt_generated_class_jar"), - BUILD_KOTLIN("--build_kotlin"), - STRICT_KOTLIN_DEPS("--strict_kotlin_deps"), - REDUCED_CLASSPATH_MODE("--reduced_classpath_mode"), - INSTRUMENT_COVERAGE("--instrument_coverage"), - KSP_GENERATED_JAVA_SRCJAR("--ksp_generated_java_srcjar"), + enum class KotlinBuilderFlags( + override val flag: String, + ) : Flag { + TARGET_LABEL("--target_label"), + CLASSPATH("--classpath"), + DIRECT_DEPENDENCIES("--direct_dependencies"), + DEPS_ARTIFACTS("--deps_artifacts"), + SOURCES("--sources"), + SOURCE_JARS("--source_jars"), + PROCESSOR_PATH("--processorpath"), + PROCESSORS("--processors"), + STUBS_PLUGIN_OPTIONS("--stubs_plugin_options"), + STUBS_PLUGIN_CLASS_PATH("--stubs_plugin_classpath"), + COMPILER_PLUGIN_OPTIONS("--compiler_plugin_options"), + COMPILER_PLUGIN_CLASS_PATH("--compiler_plugin_classpath"), + OUTPUT("--output"), + RULE_KIND("--rule_kind"), + MODULE_NAME("--kotlin_module_name"), + PASSTHROUGH_FLAGS("--kotlin_passthrough_flags"), + API_VERSION("--kotlin_api_version"), + LANGUAGE_VERSION("--kotlin_language_version"), + JVM_TARGET("--kotlin_jvm_target"), + OUTPUT_SRCJAR("--kotlin_output_srcjar"), + GENERATED_CLASSDIR("--kotlin_generated_classdir"), + FRIEND_PATHS("--kotlin_friend_paths"), + OUTPUT_JDEPS("--kotlin_output_jdeps"), + OUTPUT_JS_JAR("--kotlin_output_js_jar"), + JS_PASSTHROUGH_FLAGS("--kotlin_js_passthrough_flags"), + JS_LIBRARIES("--kotlin_js_libraries"), + DEBUG("--kotlin_debug_tags"), + TASK_ID("--kotlin_task_id"), + ABI_JAR("--abi_jar"), + GENERATED_JAVA_SRC_JAR("--generated_java_srcjar"), + GENERATED_JAVA_STUB_JAR("--kapt_generated_stub_jar"), + GENERATED_CLASS_JAR("--kapt_generated_class_jar"), + BUILD_KOTLIN("--build_kotlin"), + STRICT_KOTLIN_DEPS("--strict_kotlin_deps"), + REDUCED_CLASSPATH_MODE("--reduced_classpath_mode"), + INSTRUMENT_COVERAGE("--instrument_coverage"), + KSP_GENERATED_JAVA_SRCJAR("--ksp_generated_java_srcjar"), + } } - } - fun build( - taskContext: WorkerContext.TaskContext, - args: List, - ): Int { - val (argMap, compileContext) = buildContext(taskContext, args) - var success = false - var status = 0 - try { - @Suppress("WHEN_ENUM_CAN_BE_NULL_IN_JAVA") - when (compileContext.info.platform) { - Platform.JVM -> executeJvmTask(compileContext, taskContext.directory, argMap) - Platform.JS -> executeJsTask(compileContext, taskContext.directory, argMap) - Platform.UNRECOGNIZED -> throw IllegalStateException( - "unrecognized platform: ${compileContext.info}", - ) + fun build( + taskContext: WorkerContext.TaskContext, + args: List, + ): Int { + val (argMap, compileContext) = buildContext(taskContext, args) + var success = false + var status = 0 + try { + @Suppress("WHEN_ENUM_CAN_BE_NULL_IN_JAVA") + when (compileContext.info.platform) { + Platform.JVM -> executeJvmTask(compileContext, taskContext.directory, argMap) + Platform.JS -> executeJsTask(compileContext, taskContext.directory, argMap) + Platform.UNRECOGNIZED -> throw IllegalStateException( + "unrecognized platform: ${compileContext.info}", + ) + } + success = true + } catch (ex: CompilationStatusException) { + taskContext.error { "Compilation failure: ${ex.message}" } + status = ex.status + } catch (throwable: Throwable) { + taskContext.error(throwable) { "Uncaught exception" } + } finally { + compileContext.finalize(success) } - success = true - } catch (ex: CompilationStatusException) { - taskContext.error() { "Compilation failure: ${ex.message}" } - status = ex.status - } catch (throwable: Throwable) { - taskContext.error(throwable) { "Uncaught exception" } - } finally { - compileContext.finalize(success) + return status } - return status - } - private fun buildContext( - ctx: WorkerContext.TaskContext, - args: List, - ): Pair { - check(args.isNotEmpty()) { "expected at least a single arg got: ${args.joinToString(" ")}" } - val lines = FLAGFILE_RE.matchEntire(args[0])?.groups?.get(1)?.let { - Files.readAllLines(FileSystems.getDefault().getPath(it.value), StandardCharsets.UTF_8) - } ?: args + private fun buildContext( + ctx: WorkerContext.TaskContext, + args: List, + ): Pair { + check(args.isNotEmpty()) { "expected at least a single arg got: ${args.joinToString(" ")}" } + val lines = + FLAGFILE_RE.matchEntire(args[0])?.groups?.get(1)?.let { + Files.readAllLines(FileSystems.getDefault().getPath(it.value), StandardCharsets.UTF_8) + } ?: args - val argMap = ArgMaps.from(lines) - val info = buildTaskInfo(argMap).build() - val context = - CompilationTaskContext(info, ctx.asPrintStream()) - return Pair(argMap, context) - } + val argMap = ArgMaps.from(lines) + val info = buildTaskInfo(argMap).build() + val context = + CompilationTaskContext(info, ctx.asPrintStream()) + return Pair(argMap, context) + } - private fun buildTaskInfo(argMap: ArgMap): CompilationTaskInfo.Builder = - with(CompilationTaskInfo.newBuilder()) { - addAllDebug(argMap.mandatory(KotlinBuilderFlags.DEBUG)) + private fun buildTaskInfo(argMap: ArgMap): CompilationTaskInfo.Builder = + with(CompilationTaskInfo.newBuilder()) { + addAllDebug(argMap.mandatory(KotlinBuilderFlags.DEBUG)) - label = argMap.mandatorySingle(KotlinBuilderFlags.TARGET_LABEL) - argMap.mandatorySingle(KotlinBuilderFlags.RULE_KIND).split("_").also { - check(it.size == 3 && it[0] == "kt") { "invalid rule kind $it" } - platform = checkNotNull(Platform.valueOf(it[1].uppercase())) { - "unrecognized platform ${it[1]}" - } - ruleKind = checkNotNull(RuleKind.valueOf(it[2].uppercase())) { - "unrecognized rule kind ${it[2]}" + label = argMap.mandatorySingle(KotlinBuilderFlags.TARGET_LABEL) + argMap.mandatorySingle(KotlinBuilderFlags.RULE_KIND).split("_").also { + check(it.size == 3 && it[0] == "kt") { "invalid rule kind $it" } + platform = + checkNotNull(Platform.valueOf(it[1].uppercase())) { + "unrecognized platform ${it[1]}" + } + ruleKind = + checkNotNull(RuleKind.valueOf(it[2].uppercase())) { + "unrecognized rule kind ${it[2]}" + } } - } - moduleName = argMap.mandatorySingle(KotlinBuilderFlags.MODULE_NAME).also { - check(it.isNotBlank()) { "--kotlin_module_name should not be blank" } - } - addAllPassthroughFlags(argMap.optional(KotlinBuilderFlags.PASSTHROUGH_FLAGS) ?: emptyList()) + moduleName = + argMap.mandatorySingle(KotlinBuilderFlags.MODULE_NAME).also { + check(it.isNotBlank()) { "--kotlin_module_name should not be blank" } + } + addAllPassthroughFlags(argMap.optional(KotlinBuilderFlags.PASSTHROUGH_FLAGS) ?: emptyList()) - argMap.optional(KotlinBuilderFlags.FRIEND_PATHS)?.let(::addAllFriendPaths) - toolchainInfoBuilder.commonBuilder.apiVersion = - argMap.mandatorySingle(KotlinBuilderFlags.API_VERSION) - toolchainInfoBuilder.commonBuilder.languageVersion = - argMap.mandatorySingle(KotlinBuilderFlags.LANGUAGE_VERSION) - strictKotlinDeps = argMap.mandatorySingle(KotlinBuilderFlags.STRICT_KOTLIN_DEPS) - reducedClasspathMode = argMap.mandatorySingle(KotlinBuilderFlags.REDUCED_CLASSPATH_MODE) - this - } + argMap.optional(KotlinBuilderFlags.FRIEND_PATHS)?.let(::addAllFriendPaths) + toolchainInfoBuilder.commonBuilder.apiVersion = + argMap.mandatorySingle(KotlinBuilderFlags.API_VERSION) + toolchainInfoBuilder.commonBuilder.languageVersion = + argMap.mandatorySingle(KotlinBuilderFlags.LANGUAGE_VERSION) + strictKotlinDeps = argMap.mandatorySingle(KotlinBuilderFlags.STRICT_KOTLIN_DEPS) + reducedClasspathMode = argMap.mandatorySingle(KotlinBuilderFlags.REDUCED_CLASSPATH_MODE) + this + } - private fun executeJsTask( - context: CompilationTaskContext, - workingDir: Path, - argMap: ArgMap, - ) = - buildJsTask(context.info, workingDir, argMap).let { jsTask -> + private fun executeJsTask( + context: CompilationTaskContext, + workingDir: Path, + argMap: ArgMap, + ) = buildJsTask(context.info, workingDir, argMap).let { jsTask -> context.whenTracing { printProto("js task input", jsTask) } jsTaskExecutor.execute(context, jsTask) } - private fun buildJsTask( - info: CompilationTaskInfo, - workingDir: Path, - argMap: ArgMap, - ): JsCompilationTask = - with(JsCompilationTask.newBuilder()) { - this.info = info + private fun buildJsTask( + info: CompilationTaskInfo, + workingDir: Path, + argMap: ArgMap, + ): JsCompilationTask = + with(JsCompilationTask.newBuilder()) { + this.info = info - with(directoriesBuilder) { - temp = workingDir.toString() - } + with(directoriesBuilder) { + temp = workingDir.toString() + } - with(inputsBuilder) { - addAllLibraries(argMap.mandatory(KotlinBuilderFlags.JS_LIBRARIES)) - addAllKotlinSources(argMap.mandatory(KotlinBuilderFlags.SOURCES)) - } - with(outputsBuilder) { - js = argMap.mandatorySingle(KotlinBuilderFlags.OUTPUT) - jar = argMap.mandatorySingle(KotlinBuilderFlags.OUTPUT_JS_JAR) - srcjar = argMap.mandatorySingle(KotlinBuilderFlags.OUTPUT_SRCJAR) + with(inputsBuilder) { + addAllLibraries(argMap.mandatory(KotlinBuilderFlags.JS_LIBRARIES)) + addAllKotlinSources(argMap.mandatory(KotlinBuilderFlags.SOURCES)) + } + with(outputsBuilder) { + js = argMap.mandatorySingle(KotlinBuilderFlags.OUTPUT) + jar = argMap.mandatorySingle(KotlinBuilderFlags.OUTPUT_JS_JAR) + srcjar = argMap.mandatorySingle(KotlinBuilderFlags.OUTPUT_SRCJAR) + } + addAllPassThroughFlags(argMap.mandatory(KotlinBuilderFlags.JS_PASSTHROUGH_FLAGS)) + build() } - addAllPassThroughFlags(argMap.mandatory(KotlinBuilderFlags.JS_PASSTHROUGH_FLAGS)) - build() - } - private fun executeJvmTask( - context: CompilationTaskContext, - workingDir: Path, - argMap: ArgMap, - ) { - val task = buildJvmTask(context.info, workingDir, argMap) - context.whenTracing { - printProto("jvm task message:", task) + private fun executeJvmTask( + context: CompilationTaskContext, + workingDir: Path, + argMap: ArgMap, + ) { + val task = buildJvmTask(context.info, workingDir, argMap) + context.whenTracing { + printProto("jvm task message:", task) + } + jvmTaskExecutor.execute(context, task) } - jvmTaskExecutor.execute(context, task) - } - private fun buildJvmTask( - info: CompilationTaskInfo, - workingDir: Path, - argMap: ArgMap, - ): JvmCompilationTask = - JvmCompilationTask.newBuilder().let { root -> - root.info = info + private fun buildJvmTask( + info: CompilationTaskInfo, + workingDir: Path, + argMap: ArgMap, + ): JvmCompilationTask = + JvmCompilationTask.newBuilder().let { root -> + root.info = info - root.compileKotlin = argMap.mandatorySingle(KotlinBuilderFlags.BUILD_KOTLIN).toBoolean() - root.instrumentCoverage = argMap.mandatorySingle( - KotlinBuilderFlags.INSTRUMENT_COVERAGE, - ).toBoolean() + root.compileKotlin = argMap.mandatorySingle(KotlinBuilderFlags.BUILD_KOTLIN).toBoolean() + root.instrumentCoverage = + argMap + .mandatorySingle( + KotlinBuilderFlags.INSTRUMENT_COVERAGE, + ).toBoolean() - with(root.outputsBuilder) { - argMap.optionalSingle(KotlinBuilderFlags.OUTPUT)?.let { jar = it } - argMap.optionalSingle(KotlinBuilderFlags.OUTPUT_SRCJAR)?.let { srcjar = it } + with(root.outputsBuilder) { + argMap.optionalSingle(KotlinBuilderFlags.OUTPUT)?.let { jar = it } + argMap.optionalSingle(KotlinBuilderFlags.OUTPUT_SRCJAR)?.let { srcjar = it } - argMap.optionalSingle(KotlinBuilderFlags.OUTPUT_JDEPS)?.apply { jdeps = this } - argMap.optionalSingle(KotlinBuilderFlags.GENERATED_JAVA_SRC_JAR)?.apply { - generatedJavaSrcJar = this - } - argMap.optionalSingle(KotlinBuilderFlags.GENERATED_JAVA_STUB_JAR)?.apply { - generatedJavaStubJar = this - } - argMap.optionalSingle(KotlinBuilderFlags.ABI_JAR)?.let { abijar = it } - argMap.optionalSingle(KotlinBuilderFlags.GENERATED_CLASS_JAR)?.let { - generatedClassJar = it - } - argMap.optionalSingle(KotlinBuilderFlags.KSP_GENERATED_JAVA_SRCJAR)?.let { - generatedKspSrcJar = it + argMap.optionalSingle(KotlinBuilderFlags.OUTPUT_JDEPS)?.apply { jdeps = this } + argMap.optionalSingle(KotlinBuilderFlags.GENERATED_JAVA_SRC_JAR)?.apply { + generatedJavaSrcJar = this + } + argMap.optionalSingle(KotlinBuilderFlags.GENERATED_JAVA_STUB_JAR)?.apply { + generatedJavaStubJar = this + } + argMap.optionalSingle(KotlinBuilderFlags.ABI_JAR)?.let { abijar = it } + argMap.optionalSingle(KotlinBuilderFlags.GENERATED_CLASS_JAR)?.let { + generatedClassJar = it + } + argMap.optionalSingle(KotlinBuilderFlags.KSP_GENERATED_JAVA_SRCJAR)?.let { + generatedKspSrcJar = it + } } - } - with(root.directoriesBuilder) { - val moduleName = argMap.mandatorySingle(KotlinBuilderFlags.MODULE_NAME) - classes = - workingDir.resolveNewDirectories(getOutputDirPath(moduleName, "classes")).toString() - javaClasses = - workingDir.resolveNewDirectories(getOutputDirPath(moduleName, "java_classes")).toString() - if (argMap.hasAll(KotlinBuilderFlags.ABI_JAR)) { - abiClasses = - workingDir.resolveNewDirectories(getOutputDirPath(moduleName, "abi_classes")).toString() + with(root.directoriesBuilder) { + val moduleName = argMap.mandatorySingle(KotlinBuilderFlags.MODULE_NAME) + classes = + workingDir.resolveNewDirectories(getOutputDirPath(moduleName, "classes")).toString() + javaClasses = + workingDir + .resolveNewDirectories( + getOutputDirPath(moduleName, "java_classes"), + ).toString() + if (argMap.hasAll(KotlinBuilderFlags.ABI_JAR)) { + abiClasses = + workingDir + .resolveNewDirectories( + getOutputDirPath(moduleName, "abi_classes"), + ).toString() + } + generatedClasses = + workingDir + .resolveNewDirectories(getOutputDirPath(moduleName, "generated_classes")) + .toString() + temp = + workingDir + .resolveNewDirectories( + getOutputDirPath(moduleName, "temp"), + ).toString() + generatedSources = + workingDir + .resolveNewDirectories(getOutputDirPath(moduleName, "generated_sources")) + .toString() + generatedJavaSources = + workingDir + .resolveNewDirectories(getOutputDirPath(moduleName, "generated_java_sources")) + .toString() + generatedStubClasses = + workingDir.resolveNewDirectories(getOutputDirPath(moduleName, "stubs")).toString() + coverageMetadataClasses = + workingDir + .resolveNewDirectories(getOutputDirPath(moduleName, "coverage-metadata")) + .toString() } - generatedClasses = - workingDir.resolveNewDirectories(getOutputDirPath(moduleName, "generated_classes")) - .toString() - temp = workingDir.resolveNewDirectories( - getOutputDirPath(moduleName, "temp"), - ).toString() - generatedSources = - workingDir.resolveNewDirectories(getOutputDirPath(moduleName, "generated_sources")) - .toString() - generatedJavaSources = - workingDir.resolveNewDirectories(getOutputDirPath(moduleName, "generated_java_sources")) - .toString() - generatedStubClasses = - workingDir.resolveNewDirectories(getOutputDirPath(moduleName, "stubs")).toString() - coverageMetadataClasses = - workingDir.resolveNewDirectories(getOutputDirPath(moduleName, "coverage-metadata")) - .toString() - } - - with(root.inputsBuilder) { - addAllClasspath(argMap.mandatory(KotlinBuilderFlags.CLASSPATH)) - addAllDepsArtifacts( - argMap.optional(KotlinBuilderFlags.DEPS_ARTIFACTS) ?: emptyList(), - ) - addAllDirectDependencies(argMap.mandatory(KotlinBuilderFlags.DIRECT_DEPENDENCIES)) - addAllProcessors(argMap.optional(KotlinBuilderFlags.PROCESSORS) ?: emptyList()) - addAllProcessorpaths(argMap.optional(KotlinBuilderFlags.PROCESSOR_PATH) ?: emptyList()) + with(root.inputsBuilder) { + addAllClasspath(argMap.mandatory(KotlinBuilderFlags.CLASSPATH)) + addAllDepsArtifacts( + argMap.optional(KotlinBuilderFlags.DEPS_ARTIFACTS) ?: emptyList(), + ) + addAllDirectDependencies(argMap.mandatory(KotlinBuilderFlags.DIRECT_DEPENDENCIES)) - addAllStubsPluginOptions( - argMap.optional(KotlinBuilderFlags.STUBS_PLUGIN_OPTIONS) ?: emptyList(), - ) - addAllStubsPluginClasspath( - argMap.optional(KotlinBuilderFlags.STUBS_PLUGIN_CLASS_PATH) ?: emptyList(), - ) + addAllProcessors(argMap.optional(KotlinBuilderFlags.PROCESSORS) ?: emptyList()) + addAllProcessorpaths(argMap.optional(KotlinBuilderFlags.PROCESSOR_PATH) ?: emptyList()) - addAllCompilerPluginOptions( - argMap.optional(KotlinBuilderFlags.COMPILER_PLUGIN_OPTIONS) ?: emptyList(), - ) - addAllCompilerPluginClasspath( - argMap.optional(KotlinBuilderFlags.COMPILER_PLUGIN_CLASS_PATH) ?: emptyList(), - ) + addAllStubsPluginOptions( + argMap.optional(KotlinBuilderFlags.STUBS_PLUGIN_OPTIONS) ?: emptyList(), + ) + addAllStubsPluginClasspath( + argMap.optional(KotlinBuilderFlags.STUBS_PLUGIN_CLASS_PATH) ?: emptyList(), + ) - argMap.optional(KotlinBuilderFlags.SOURCES) - ?.iterator() - ?.partitionJvmSources( - { addKotlinSources(it) }, - { addJavaSources(it) }, + addAllCompilerPluginOptions( + argMap.optional(KotlinBuilderFlags.COMPILER_PLUGIN_OPTIONS) ?: emptyList(), + ) + addAllCompilerPluginClasspath( + argMap.optional(KotlinBuilderFlags.COMPILER_PLUGIN_CLASS_PATH) ?: emptyList(), ) - argMap.optional(KotlinBuilderFlags.SOURCE_JARS) - ?.also { - addAllSourceJars(it) - } - } - with(root.infoBuilder) { - toolchainInfoBuilder.jvmBuilder.jvmTarget = - argMap.mandatorySingle(KotlinBuilderFlags.JVM_TARGET) + argMap + .optional(KotlinBuilderFlags.SOURCES) + ?.iterator() + ?.partitionJvmSources( + { addKotlinSources(it) }, + { addJavaSources(it) }, + ) + argMap + .optional(KotlinBuilderFlags.SOURCE_JARS) + ?.also { + addAllSourceJars(it) + } + } + + with(root.infoBuilder) { + toolchainInfoBuilder.jvmBuilder.jvmTarget = + argMap.mandatorySingle(KotlinBuilderFlags.JVM_TARGET) + } + root.build() } - root.build() - } - private fun getOutputDirPath( - moduleName: String, - dirName: String, - ) = - "_kotlinc/${moduleName}_jvm/$dirName" -} + private fun getOutputDirPath( + moduleName: String, + dirName: String, + ) = "_kotlinc/${moduleName}_jvm/$dirName" + } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/MergeJdeps.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/MergeJdeps.kt index 2b9bfde3d..30ada5576 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/MergeJdeps.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/MergeJdeps.kt @@ -23,11 +23,18 @@ import io.bazel.worker.Work import io.bazel.worker.WorkerContext import javax.inject.Inject -class MergeJdeps @Inject constructor(private val merger: JdepsMerger) : Work { - override fun invoke(ctx: WorkerContext.TaskContext, args: Iterable): Status { - if (merger.execute(ctx, args.toList()) != 0) { - return Status.ERROR +class MergeJdeps + @Inject + constructor( + private val merger: JdepsMerger, + ) : Work { + override fun invoke( + ctx: WorkerContext.TaskContext, + args: Iterable, + ): Status { + if (merger.execute(ctx, args.toList()) != 0) { + return Status.ERROR + } + return Status.SUCCESS } - return Status.SUCCESS } -} diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/js/Kotlin2JsTaskExecutor.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/js/Kotlin2JsTaskExecutor.kt index 122cab678..b9ded3357 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/js/Kotlin2JsTaskExecutor.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/js/Kotlin2JsTaskExecutor.kt @@ -19,78 +19,87 @@ import kotlin.io.path.absolutePathString import kotlin.io.path.nameWithoutExtension @Singleton -class Kotlin2JsTaskExecutor @Inject constructor( - private val invoker: KotlinToolchain.K2JSCompilerInvoker, -) { +class Kotlin2JsTaskExecutor + @Inject + constructor( + private val invoker: KotlinToolchain.K2JSCompilerInvoker, + ) { + private val fileSystem: FileSystem = FileSystems.getDefault() - private val fileSystem: FileSystem = FileSystems.getDefault() + fun execute( + context: CompilationTaskContext, + task: JsCompilationTask, + ) { + val outputDirectory = task.compile(context) + task.createJar(outputDirectory) + task.createSourceJar() + } - fun execute( - context: CompilationTaskContext, - task: JsCompilationTask, - ) { - val outputDirectory = task.compile(context) - task.createJar(outputDirectory) - task.createSourceJar() - } + private fun JsCompilationTask.compile(context: CompilationTaskContext): Path { + val jsOut = fileSystem.getPath(outputs.js) + val outputDirectory = jsOut.parent + val baseName = jsOut.fileName.nameWithoutExtension + val mapOut = outputDirectory.resolve("$baseName.js.map") + val workingDirectory = fileSystem.getPath(directories.temp) - private fun JsCompilationTask.compile(context: CompilationTaskContext): Path { - val jsOut = fileSystem.getPath(outputs.js) - val outputDirectory = jsOut.parent - val baseName = jsOut.fileName.nameWithoutExtension - val mapOut = outputDirectory.resolve("$baseName.js.map") - val workingDirectory = fileSystem.getPath(directories.temp) + val execRoot = fileSystem.getPath(".").absolute() - val execRoot = fileSystem.getPath(".").absolute() + val args = + mutableListOf().apply { + addAll(passThroughFlagsList) + add("-Xdisable-default-scripting-plugin") + add("-Xir-produce-js") + add("-progressive") + add("-Xoptimize-generated-js=false") + addAll( + "-libraries", + inputs.librariesList + .map { + execRoot + .resolve( + it, + ).absolutePathString() + }.joinToString(":"), + ) + addAll("-ir-output-name", baseName) + addAll("-ir-output-dir", workingDirectory.toString()) + addAll("-Xir-module-name=${info.moduleName}") + addAll(inputs.kotlinSourcesList.map { execRoot.resolve(it).absolutePathString() }) + } - val args = mutableListOf().apply { - addAll(passThroughFlagsList) - add("-Xdisable-default-scripting-plugin") - add("-Xir-produce-js") - add("-progressive") - add("-Xoptimize-generated-js=false") - addAll( - "-libraries", - inputs.librariesList.map { execRoot.resolve(it).absolutePathString() }.joinToString(":"), - ) - addAll("-ir-output-name", baseName) - addAll("-ir-output-dir", workingDirectory.toString()) - addAll("-Xir-module-name=${info.moduleName}") - addAll(inputs.kotlinSourcesList.map { execRoot.resolve(it).absolutePathString() }) - } + context.whenTracing { printLines("js compile args", args) } + context.executeCompilerTask(args, invoker::compile) + context.whenTracing { + printLines( + "outputs", + Files.walk(outputDirectory).map { p -> p.toString() }.collect(Collectors.toList()), + ) + } + Files.copy(workingDirectory.resolve(jsOut.fileName), jsOut) + Files.copy(workingDirectory.resolve(mapOut.fileName), mapOut) - context.whenTracing { printLines("js compile args", args) } - context.executeCompilerTask(args, invoker::compile) - context.whenTracing { - printLines( - "outputs", - Files.walk(outputDirectory).map { p -> p.toString() }.collect(Collectors.toList()), - ) + return workingDirectory } - Files.copy(workingDirectory.resolve(jsOut.fileName), jsOut) - Files.copy(workingDirectory.resolve(mapOut.fileName), mapOut) - - return workingDirectory - } - private fun JsCompilationTask.createSourceJar() { - try { - SourceJarCreator(fileSystem.getPath(outputs.srcjar), false).also { creator -> - creator.addSources(inputs.kotlinSourcesList.map { fileSystem.getPath(it) }.stream()) - }.execute() - } catch (ex: Throwable) { - throw CompilationException("could not create source jar", ex) + private fun JsCompilationTask.createSourceJar() { + try { + SourceJarCreator(fileSystem.getPath(outputs.srcjar), false) + .also { creator -> + creator.addSources(inputs.kotlinSourcesList.map { fileSystem.getPath(it) }.stream()) + }.execute() + } catch (ex: Throwable) { + throw CompilationException("could not create source jar", ex) + } } - } - private fun JsCompilationTask.createJar(jsDirectoryPath: Path) { - try { - JarCreator(fileSystem.getPath(outputs.jar)).use { creator -> - creator.addDirectory(jsDirectoryPath) - creator.execute() + private fun JsCompilationTask.createJar(jsDirectoryPath: Path) { + try { + JarCreator(fileSystem.getPath(outputs.jar)).use { creator -> + creator.addDirectory(jsDirectoryPath) + creator.execute() + } + } catch (ex: Throwable) { + throw CompilationException("error creating js jar", ex) } - } catch (ex: Throwable) { - throw CompilationException("error creating js jar", ex) } } -} diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/CompilationArgs.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/CompilationArgs.kt index cbc50eb78..7186cfa99 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/CompilationArgs.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/CompilationArgs.kt @@ -32,7 +32,6 @@ class CompilationArgs( val args: MutableList = mutableListOf(), private val dfs: FileSystem = FileSystems.getDefault(), ) { - class StringConditional( val value: String, val parent: CompilationArgs, @@ -59,9 +58,7 @@ class CompilationArgs( ): SetFlag } - fun plugin(p: KotlinToolchain.CompilerPlugin): CompilationArgs { - return plugin(p) {} - } + fun plugin(p: KotlinToolchain.CompilerPlugin): CompilationArgs = plugin(p) {} fun plugin( p: KotlinToolchain.CompilerPlugin, @@ -91,13 +88,12 @@ class CompilationArgs( return this } - fun given(value: String): StringConditional { - return StringConditional(value, this) - } + fun given(value: String): StringConditional = StringConditional(value, this) - operator fun plus(other: CompilationArgs): CompilationArgs = CompilationArgs( - (args.asSequence() + other.args.asSequence()).toMutableList(), - ) + operator fun plus(other: CompilationArgs): CompilationArgs = + CompilationArgs( + (args.asSequence() + other.args.asSequence()).toMutableList(), + ) fun absolutePaths( paths: Collection, @@ -108,7 +104,8 @@ class CompilationArgs( } return value( toArgs( - paths.asSequence() + paths + .asSequence() .map { dfs.getPath(it) } .map(Path::toAbsolutePath), ), @@ -124,7 +121,8 @@ class CompilationArgs( } return value( toArgs( - paths.asSequence() + paths + .asSequence() .map { dfs.getPath(it) }, ), ) diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/CompilationTask.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/CompilationTask.kt index fd94ba0eb..f845b9607 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/CompilationTask.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/CompilationTask.kt @@ -48,41 +48,42 @@ import kotlin.io.path.exists private const val SOURCE_JARS_DIR = "_srcjars" -fun JvmCompilationTask.codeGenArgs(): CompilationArgs = CompilationArgs() - .absolutePaths(info.friendPathsList) { - "-Xfriend-paths=${it.joinToString(X_FRIENDS_PATH_SEPARATOR)}" - } - .flag("-d", directories.classes) - .values(info.passthroughFlagsList) +fun JvmCompilationTask.codeGenArgs(): CompilationArgs = + CompilationArgs() + .absolutePaths(info.friendPathsList) { + "-Xfriend-paths=${it.joinToString(X_FRIENDS_PATH_SEPARATOR)}" + }.flag("-d", directories.classes) + .values(info.passthroughFlagsList) fun JvmCompilationTask.baseArgs(): CompilationArgs { - val classpath = when (info.reducedClasspathMode) { - "KOTLINBUILDER_REDUCED" -> { - val transitiveDepsForCompile = mutableSetOf() - inputs.depsArtifactsList.forEach { jdepsPath -> - BufferedInputStream(Paths.get(jdepsPath).toFile().inputStream()).use { - val deps = Deps.Dependencies.parseFrom(it) - deps.dependencyList.forEach { dep -> - if (dep.kind == Deps.Dependency.Kind.EXPLICIT) { - transitiveDepsForCompile.add(dep.path) + val classpath = + when (info.reducedClasspathMode) { + "KOTLINBUILDER_REDUCED" -> { + val transitiveDepsForCompile = mutableSetOf() + inputs.depsArtifactsList.forEach { jdepsPath -> + BufferedInputStream(Paths.get(jdepsPath).toFile().inputStream()).use { + val deps = Deps.Dependencies.parseFrom(it) + deps.dependencyList.forEach { dep -> + if (dep.kind == Deps.Dependency.Kind.EXPLICIT) { + transitiveDepsForCompile.add(dep.path) + } } } } + inputs.directDependenciesList + transitiveDepsForCompile } - inputs.directDependenciesList + transitiveDepsForCompile - } - else -> inputs.classpathList - } as List + else -> inputs.classpathList + } as List return CompilationArgs() .flag("-cp") .paths( classpath + directories.generatedClasses, ) { - it.map(Path::toString) + it + .map(Path::toString) .joinToString(File.pathSeparator) - } - .flag("-api-version", info.toolchainInfo.common.apiVersion) + }.flag("-api-version", info.toolchainInfo.common.apiVersion) .flag("-language-version", info.toolchainInfo.common.languageVersion) .flag("-jvm-target", info.toolchainInfo.jvm.jvmTarget) .flag("-module-name", info.moduleName) @@ -97,26 +98,26 @@ internal fun JvmCompilationTask.plugins( xFlag("plugin", it) } - val optionTokens = mapOf( - "{generatedClasses}" to directories.generatedClasses, - "{stubs}" to directories.stubs, - "{temp}" to directories.temp, - "{generatedSources}" to directories.generatedSources, - "{classpath}" to classpath.joinToString(File.pathSeparator), - ) + val optionTokens = + mapOf( + "{generatedClasses}" to directories.generatedClasses, + "{stubs}" to directories.stubs, + "{temp}" to directories.temp, + "{generatedSources}" to directories.generatedSources, + "{classpath}" to classpath.joinToString(File.pathSeparator), + ) options.forEach { opt -> - val formatted = optionTokens.entries.fold(opt) { formatting, (token, value) -> - formatting.replace(token, value) - } + val formatted = + optionTokens.entries.fold(opt) { formatting, (token, value) -> + formatting.replace(token, value) + } flag("-P", "plugin:$formatted") } } internal fun JvmCompilationTask.preProcessingSteps( context: CompilationTaskContext, -): JvmCompilationTask { - return context.execute("expand sources") { expandWithSourceJarSources() } -} +): JvmCompilationTask = context.execute("expand sources") { expandWithSourceJarSources() } internal fun encodeMap(options: Map): String { val os = ByteArrayOutputStream() @@ -129,7 +130,8 @@ internal fun encodeMap(options: Map): String { } oos.flush() - return Base64.getEncoder() + return Base64 + .getEncoder() .encodeToString(os.toByteArray()) } @@ -138,77 +140,82 @@ internal fun JvmCompilationTask.kaptArgs( plugins: InternalCompilerPlugins, aptMode: String, ): CompilationArgs { - val javacArgs = mapOf( - "-target" to info.toolchainInfo.jvm.jvmTarget, - "-source" to info.toolchainInfo.jvm.jvmTarget, - ) + val javacArgs = + mapOf( + "-target" to info.toolchainInfo.jvm.jvmTarget, + "-source" to info.toolchainInfo.jvm.jvmTarget, + ) return CompilationArgs().apply { xFlag("plugin", plugins.kapt.jarPath) - val values = arrayOf( - "sources" to listOf(directories.generatedJavaSources), - "classes" to listOf(directories.generatedClasses), - "stubs" to listOf(directories.stubs), - "incrementalData" to listOf(directories.incrementalData), - "javacArguments" to listOf(javacArgs.let(::encodeMap)), - "correctErrorTypes" to listOf("false"), - "verbose" to listOf(context.whenTracing { "true" } ?: "false"), - "apclasspath" to inputs.processorpathsList, - "aptMode" to listOf(aptMode), - ) - val version = info.toolchainInfo.common.apiVersion.toFloat() + val values = + arrayOf( + "sources" to listOf(directories.generatedJavaSources), + "classes" to listOf(directories.generatedClasses), + "stubs" to listOf(directories.stubs), + "incrementalData" to listOf(directories.incrementalData), + "javacArguments" to listOf(javacArgs.let(::encodeMap)), + "correctErrorTypes" to listOf("false"), + "verbose" to listOf(context.whenTracing { "true" } ?: "false"), + "apclasspath" to inputs.processorpathsList, + "aptMode" to listOf(aptMode), + ) + val version = + info.toolchainInfo.common.apiVersion + .toFloat() when { - version < 1.5 -> base64Encode( - "-P", - *values + ("processors" to inputs.processorsList).asKeyToCommaList(), - ) { enc -> "plugin:${plugins.kapt.id}:configuration=$enc" } - else -> repeatFlag( - "-P", - *values + ("processors" to inputs.processorsList), - ) { option, value -> - "plugin:${plugins.kapt.id}:$option=$value" - } + version < 1.5 -> + base64Encode( + "-P", + *values + ("processors" to inputs.processorsList).asKeyToCommaList(), + ) { enc -> "plugin:${plugins.kapt.id}:configuration=$enc" } + else -> + repeatFlag( + "-P", + *values + ("processors" to inputs.processorsList), + ) { option, value -> + "plugin:${plugins.kapt.id}:$option=$value" + } } } } -internal fun JvmCompilationTask.kspArgs( - plugins: InternalCompilerPlugins, -): CompilationArgs { - return CompilationArgs().apply { +internal fun JvmCompilationTask.kspArgs(plugins: InternalCompilerPlugins): CompilationArgs = + CompilationArgs().apply { plugin(plugins.kspSymbolProcessingCommandLine) plugin(plugins.kspSymbolProcessingApi) { flag("-Xallow-no-source-files") - val values = arrayOf( - "apclasspath" to listOf(inputs.processorpathsList.joinToString(File.pathSeparator)), - // projectBaseDir shouldn't matter because incremental is disabled - "projectBaseDir" to listOf(directories.incrementalData), - // Disable incremental mode - "incremental" to listOf("false"), - // Directory where class files are written to. Files written to this directory are class - // files being written directly from the annotation processor, not Kotlinc - "classOutputDir" to listOf(directories.generatedClasses), - // Directory where generated Java sources files are written to - "javaOutputDir" to listOf(directories.generatedJavaSources), - // Directory where generated Kotlin sources files are written to - "kotlinOutputDir" to listOf(directories.generatedSources), - // Directory where META-INF data is written to. This might not be the most ideal place to - // write this. Maybe just directly to the classes directory? - "resourceOutputDir" to listOf(directories.generatedSources), - // TODO(bencodes) Not sure what this directory is yet. - "kspOutputDir" to listOf(directories.incrementalData), - // Directory to write KSP caches. Shouldn't matter because incremental is disabled - "cachesDir" to listOf(directories.incrementalData), - // Set withCompilation to false because we run this as part of the standard kotlinc pass - // If we ever want to flip this to true, we probably want to integrate this directly - // into the KotlinCompile action. - "withCompilation" to listOf("false"), - // Set returnOkOnError to false because we want to fail the build if there are any errors - "returnOkOnError" to listOf("false"), - // TODO(bencodes) This should probably be enabled via some KSP options - "allWarningsAsErrors" to listOf("false"), - ) + val values = + arrayOf( + "apclasspath" to listOf(inputs.processorpathsList.joinToString(File.pathSeparator)), + // projectBaseDir shouldn't matter because incremental is disabled + "projectBaseDir" to listOf(directories.incrementalData), + // Disable incremental mode + "incremental" to listOf("false"), + // Directory where class files are written to. Files written to this directory are class + // files being written directly from the annotation processor, not Kotlinc + "classOutputDir" to listOf(directories.generatedClasses), + // Directory where generated Java sources files are written to + "javaOutputDir" to listOf(directories.generatedJavaSources), + // Directory where generated Kotlin sources files are written to + "kotlinOutputDir" to listOf(directories.generatedSources), + // Directory where META-INF data is written to. This might not be the most ideal place to + // write this. Maybe just directly to the classes directory? + "resourceOutputDir" to listOf(directories.generatedSources), + // TODO(bencodes) Not sure what this directory is yet. + "kspOutputDir" to listOf(directories.incrementalData), + // Directory to write KSP caches. Shouldn't matter because incremental is disabled + "cachesDir" to listOf(directories.incrementalData), + // Set withCompilation to false because we run this as part of the standard kotlinc pass + // If we ever want to flip this to true, we probably want to integrate this directly + // into the KotlinCompile action. + "withCompilation" to listOf("false"), + // Set returnOkOnError to false because we want to fail the build if there are any errors + "returnOkOnError" to listOf("false"), + // TODO(bencodes) This should probably be enabled via some KSP options + "allWarningsAsErrors" to listOf("false"), + ) values.forEach { pair -> pair.second.forEach { value -> @@ -217,7 +224,6 @@ internal fun JvmCompilationTask.kspArgs( } } } -} private fun Pair>.asKeyToCommaList() = first to listOf(second.joinToString(",")) @@ -231,7 +237,7 @@ internal fun JvmCompilationTask.runPlugins( ( inputs.processorsList.isEmpty() && inputs.stubsPluginClasspathList.isEmpty() - ) || + ) || inputs.kotlinSourcesList.isEmpty() ) { return this @@ -252,15 +258,19 @@ private fun JvmCompilationTask.runKaptPlugin( compiler: KotlinToolchain.KotlincInvoker, ): JvmCompilationTask { return context.execute("kapt (${inputs.processorsList.joinToString(", ")})") { - baseArgs().plus( - plugins( - options = inputs.stubsPluginOptionsList, - classpath = inputs.stubsPluginClasspathList, - ), - ).plus( - kaptArgs(context, plugins, "stubsAndApt"), - ).flag("-d", directories.generatedClasses).values(inputs.kotlinSourcesList) - .values(inputs.javaSourcesList).list().let { args -> + baseArgs() + .plus( + plugins( + options = inputs.stubsPluginOptionsList, + classpath = inputs.stubsPluginClasspathList, + ), + ).plus( + kaptArgs(context, plugins, "stubsAndApt"), + ).flag("-d", directories.generatedClasses) + .values(inputs.kotlinSourcesList) + .values(inputs.javaSourcesList) + .list() + .let { args -> context.executeCompilerTask( args, compiler::compile, @@ -287,7 +297,9 @@ private fun JvmCompilationTask.runKspPlugin( .plus(kspArgs(plugins)) .flag("-d", directories.generatedClasses) .values(inputs.kotlinSourcesList) - .values(inputs.javaSourcesList).list().let { args -> + .values(inputs.javaSourcesList) + .list() + .let { args -> context.executeCompilerTask( args, compiler::compile, @@ -407,12 +419,12 @@ fun JvmCompilationTask.compileKotlin( return emptyList() } else { return ( - args + plugins( - options = inputs.compilerPluginOptionsList, - classpath = inputs.compilerPluginClasspathList, - ) - ) - .values(inputs.javaSourcesList) + args + + plugins( + options = inputs.compilerPluginOptionsList, + classpath = inputs.compilerPluginClasspathList, + ) + ).values(inputs.javaSourcesList) .values(inputs.kotlinSourcesList) .flag("-d", directories.classes) .list() @@ -420,19 +432,20 @@ fun JvmCompilationTask.compileKotlin( context.whenTracing { context.printLines("compileKotlin arguments:\n", it) } - return@let context.executeCompilerTask(it, compiler::compile, printOnFail = printOnFail) + return@let context + .executeCompilerTask(it, compiler::compile, printOnFail = printOnFail) .also { context.whenTracing { printLines( "kotlinc Files Created:", - Stream.of( - directories.classes, - directories.generatedClasses, - directories.generatedSources, - directories.generatedJavaSources, - directories.temp, - ) - .map { Paths.get(it) } + Stream + .of( + directories.classes, + directories.generatedClasses, + directories.generatedSources, + directories.generatedJavaSources, + directories.temp, + ).map { Paths.get(it) } .flatMap { walk(it) } .filter { !isDirectory(it) } .map { it.toString() } @@ -459,22 +472,27 @@ internal fun JvmCompilationTask.expandWithSourceJarSources(): JvmCompilationTask ).also { it.jarFiles.addAll(inputs.sourceJarsList.map { p -> Paths.get(p) }) it.execute() - }.sourcesList.iterator(), + }.sourcesList + .iterator(), ) } private val Directories.stubs - get() = Files.createDirectories( - Paths.get(temp) - .resolve("stubs"), - ) - .toString() + get() = + Files + .createDirectories( + Paths + .get(temp) + .resolve("stubs"), + ).toString() private val Directories.incrementalData - get() = Files.createDirectories( - Paths.get(temp) - .resolve("incrementalData"), - ) - .toString() + get() = + Files + .createDirectories( + Paths + .get(temp) + .resolve("incrementalData"), + ).toString() /** * Create a new [JvmCompilationTask] with sources found in the generatedSources directory. This should be run after @@ -482,7 +500,8 @@ private val Directories.incrementalData */ fun JvmCompilationTask.expandWithGeneratedSources(): JvmCompilationTask = expandWithSources( - Stream.of(directories.generatedSources, directories.generatedJavaSources) + Stream + .of(directories.generatedSources, directories.generatedJavaSources) .map { s -> Paths.get(s) } .flatMap { p -> walk(p) } .filter { !isDirectory(it) } @@ -493,7 +512,8 @@ fun JvmCompilationTask.expandWithGeneratedSources(): JvmCompilationTask = private fun JvmCompilationTask.expandWithSources(sources: Iterator): JvmCompilationTask = updateBuilder { builder -> - sources.copyManifestFilesToGeneratedClasses(directories) + sources + .copyManifestFilesToGeneratedClasses(directories) .filterOutNonCompilableSources() .partitionJvmSources( { builder.inputsBuilder.addKotlinSources(it) }, diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JDepsGenerator.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JDepsGenerator.kt index 919de532b..47c7f138a 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JDepsGenerator.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JDepsGenerator.kt @@ -21,17 +21,19 @@ import java.nio.file.Files import java.nio.file.Paths object JDepsGenerator { - internal fun writeJdeps(path: String, jdepsContent: Deps.Dependencies) { + internal fun writeJdeps( + path: String, + jdepsContent: Deps.Dependencies, + ) { Paths.get(path).also { Files.deleteIfExists(it) FileOutputStream(Files.createFile(it).toFile()).use(jdepsContent::writeTo) } } - internal fun emptyJdeps(label: String): Deps.Dependencies { - return Deps.Dependencies.newBuilder().let { + internal fun emptyJdeps(label: String): Deps.Dependencies = + Deps.Dependencies.newBuilder().let { it.ruleLabel = label it.build() } - } } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JacocoInstrumentation.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JacocoInstrumentation.kt index e7c8cc388..28ef1a071 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JacocoInstrumentation.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JacocoInstrumentation.kt @@ -26,9 +26,10 @@ internal fun JvmCompilationTask.createCoverageInstrumentedJar() { Paths.get(directories.generatedClasses), ) - val pathsForCoverage = instrumentedClassesDirectory.resolve( - "${Paths.get(outputs.jar).fileName}-paths-for-coverage.txt", - ) + val pathsForCoverage = + instrumentedClassesDirectory.resolve( + "${Paths.get(outputs.jar).fileName}-paths-for-coverage.txt", + ) Files.write( pathsForCoverage, inputs.javaSourcesList + inputs.kotlinSourcesList, @@ -48,27 +49,35 @@ internal fun JvmCompilationTask.createCoverageInstrumentedJar() { } } -private fun instrumentRecursively(instr: Instrumenter, metadataDir: Path, root: Path) { - val visitor = object : SimpleFileVisitor() { - override fun visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult { - if (file.toFile().extension != "class") { - return FileVisitResult.CONTINUE - } +private fun instrumentRecursively( + instr: Instrumenter, + metadataDir: Path, + root: Path, +) { + val visitor = + object : SimpleFileVisitor() { + override fun visitFile( + file: Path, + attrs: BasicFileAttributes, + ): FileVisitResult { + if (file.toFile().extension != "class") { + return FileVisitResult.CONTINUE + } - val absoluteUninstrumentedCopy = Paths.get("$file.uninstrumented") - val uninstrumentedCopy = metadataDir.resolve(root.relativize(absoluteUninstrumentedCopy)) + val absoluteUninstrumentedCopy = Paths.get("$file.uninstrumented") + val uninstrumentedCopy = metadataDir.resolve(root.relativize(absoluteUninstrumentedCopy)) - Files.createDirectories(uninstrumentedCopy.parent) - Files.move(file, uninstrumentedCopy) + Files.createDirectories(uninstrumentedCopy.parent) + Files.move(file, uninstrumentedCopy) - Files.newInputStream(uninstrumentedCopy).buffered().use { input -> - Files.newOutputStream(file).buffered().use { output -> - instr.instrument(input, output, file.toString()) + Files.newInputStream(uninstrumentedCopy).buffered().use { input -> + Files.newOutputStream(file).buffered().use { output -> + instr.instrument(input, output, file.toString()) + } } - } - return FileVisitResult.CONTINUE + return FileVisitResult.CONTINUE + } } - } Files.walkFileTree(root, visitor) } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JdepsMerger.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JdepsMerger.kt index 9cfbc9702..5afacbebd 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JdepsMerger.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JdepsMerger.kt @@ -25,14 +25,15 @@ import java.util.jar.JarFile */ class JdepsMerger { companion object { - @JvmStatic private val FLAGFILE_RE = Regex("""^--flagfile=((.*)-(\d+).params)$""") /** * Declares the flags used by the java builder. */ - enum class JdepsMergerFlags(override val flag: String) : Flag { + enum class JdepsMergerFlags( + override val flag: String, + ) : Flag { INPUTS("--inputs"), OUTPUT("--output"), TARGET_LABEL("--target_label"), @@ -44,8 +45,9 @@ class JdepsMerger { JarFile(jarPath.toFile()).use { jarFile -> val manifest = jarFile.manifest ?: return JarOwner(jarPath) val attributes = manifest.mainAttributes - val label = attributes[TARGET_LABEL] as String? - ?: return JarOwner(jarPath) + val label = + attributes[TARGET_LABEL] as String? + ?: return JarOwner(jarPath) val injectingRuleKind = attributes[INJECTING_RULE_KIND] as String? return JarOwner(jarPath, label, injectingRuleKind) } @@ -107,10 +109,11 @@ class JdepsMerger { } } - val unusedLabels = kindMap.entries - .filter { it.value == Deps.Dependency.Kind.UNUSED } - .map { it.key } - .filter { it != label } + val unusedLabels = + kindMap.entries + .filter { it.value == Deps.Dependency.Kind.UNUSED } + .map { it.key } + .filter { it != label } if (unusedLabels.isNotEmpty()) { ctx.info { @@ -132,18 +135,26 @@ class JdepsMerger { } } - private data class JarOwner(val jar: Path, val label: String? = null, val aspect: String? = null) + private data class JarOwner( + val jar: Path, + val label: String? = null, + val aspect: String? = null, + ) private fun getArgs(args: List): ArgMap { check(args.isNotEmpty()) { "expected at least a single arg got: ${args.joinToString(" ")}" } - val lines = FLAGFILE_RE.matchEntire(args[0])?.groups?.get(1)?.let { - Files.readAllLines(FileSystems.getDefault().getPath(it.value), StandardCharsets.UTF_8) - } ?: args + val lines = + FLAGFILE_RE.matchEntire(args[0])?.groups?.get(1)?.let { + Files.readAllLines(FileSystems.getDefault().getPath(it.value), StandardCharsets.UTF_8) + } ?: args return ArgMaps.from(lines) } - fun execute(ctx: WorkerContext.TaskContext, args: List): Int { + fun execute( + ctx: WorkerContext.TaskContext, + args: List, + ): Int { val argMap = getArgs(args) val inputs = argMap.mandatory(JdepsMergerFlags.INPUTS) val output = argMap.mandatorySingle(JdepsMergerFlags.OUTPUT) diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JdepsParser.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JdepsParser.kt index 9d7326692..0fa64efa5 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JdepsParser.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JdepsParser.kt @@ -28,20 +28,24 @@ internal class JdepsParser private constructor( private val moduleDeps = HashMap>() private val arrowRegex = " -> ".toRegex() - private fun consumeJarLine(classJarPath: String, kind: Deps.Dependency.Kind) { + private fun consumeJarLine( + classJarPath: String, + kind: Deps.Dependency.Kind, + ) { // ignore absolute files, -- jdk jar paths etc. // only process jar files if (classJarPath.endsWith(".jar")) { - val entry = depMap.computeIfAbsent(classJarPath) { - val depBuilder = Deps.Dependency.newBuilder() - depBuilder.path = classJarPath - depBuilder.kind = kind + 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 + if (isImplicit.test(classJarPath)) { + depBuilder.kind = Deps.Dependency.Kind.IMPLICIT + } + depBuilder } - depBuilder - } // don't flip an implicit dep. if (entry.kind != Deps.Dependency.Kind.IMPLICIT) { @@ -50,10 +54,14 @@ internal class JdepsParser private constructor( } } - private fun addModuleDependency(module: String, jarFile: String) { - val entry = moduleDeps.computeIfAbsent(module) { - mutableListOf() - } + private fun addModuleDependency( + module: String, + jarFile: String, + ) { + val entry = + moduleDeps.computeIfAbsent(module) { + mutableListOf() + } entry.add(jarFile) } @@ -64,7 +72,10 @@ internal class JdepsParser private constructor( } } - private fun markFromEntry(entry: String, kind: Deps.Dependency.Kind) { + private fun markFromEntry( + entry: String, + kind: Deps.Dependency.Kind, + ) { moduleDeps[entry]?.forEach { jarPath -> val dependency = depMap[jarPath] if (dependency != null) { @@ -78,7 +89,10 @@ internal class JdepsParser private constructor( } companion object { - fun pathSuffixMatchingPredicate(directory: Path, vararg jars: String): Predicate { + fun pathSuffixMatchingPredicate( + directory: Path, + vararg jars: String, + ): Predicate { val suffixes = jars.map { directory.resolve(it).toString() } return Predicate { jar -> for (implicitJarsEnding in suffixes) { diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt index 87d6f7b2c..f8763b744 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt @@ -30,106 +30,116 @@ import javax.inject.Singleton const val X_FRIENDS_PATH_SEPARATOR = "," @Singleton -class KotlinJvmTaskExecutor @Inject internal constructor( - private val compiler: KotlinToolchain.KotlincInvoker, - private val plugins: InternalCompilerPlugins, -) { - - private fun combine(one: Throwable?, two: Throwable?): Throwable? { - return when { - one != null && two != null -> { - one.addSuppressed(two) - return one +class KotlinJvmTaskExecutor + @Inject + internal constructor( + private val compiler: KotlinToolchain.KotlincInvoker, + private val plugins: InternalCompilerPlugins, + ) { + private fun combine( + one: Throwable?, + two: Throwable?, + ): Throwable? { + return when { + one != null && two != null -> { + one.addSuppressed(two) + return one + } + one != null -> one + else -> two } - one != null -> one - else -> two } - } - fun execute(context: CompilationTaskContext, task: JvmCompilationTask) { - val preprocessedTask = task - .preProcessingSteps(context) - .runPlugins(context, plugins, compiler) + fun execute( + context: CompilationTaskContext, + task: JvmCompilationTask, + ) { + val preprocessedTask = + task + .preProcessingSteps(context) + .runPlugins(context, plugins, compiler) - context.execute("compile classes") { - preprocessedTask.apply { - sequenceOf( - runCatching { - context.execute("kotlinc") { - if (compileKotlin) { - compileKotlin( - context, - compiler, - args = baseArgs() - .given(outputs.jdeps).notEmpty { - plugin(plugins.jdeps) { - flag("output", outputs.jdeps) - flag("target_label", info.label) - inputs.directDependenciesList.forEach { - flag("direct_dependencies", it) - } - flag("strict_kotlin_deps", info.strictKotlinDeps) - } - } - .given(outputs.jar).notEmpty { - append(codeGenArgs()) - } - .given(outputs.abijar).notEmpty { - plugin(plugins.jvmAbiGen) { - flag("outputDir", directories.abiClasses) - } - given(outputs.jar).empty { - plugin(plugins.skipCodeGen) - } - }, - printOnFail = false, - ) - } else { - emptyList() + context.execute("compile classes") { + preprocessedTask.apply { + sequenceOf( + runCatching { + context.execute("kotlinc") { + if (compileKotlin) { + compileKotlin( + context, + compiler, + args = + baseArgs() + .given(outputs.jdeps) + .notEmpty { + plugin(plugins.jdeps) { + flag("output", outputs.jdeps) + flag("target_label", info.label) + inputs.directDependenciesList.forEach { + flag("direct_dependencies", it) + } + flag("strict_kotlin_deps", info.strictKotlinDeps) + } + }.given(outputs.jar) + .notEmpty { + append(codeGenArgs()) + }.given(outputs.abijar) + .notEmpty { + plugin(plugins.jvmAbiGen) { + flag("outputDir", directories.abiClasses) + } + given(outputs.jar).empty { + plugin(plugins.skipCodeGen) + } + }, + printOnFail = false, + ) + } else { + emptyList() + } } + }, + ).map { + (it.getOrNull() ?: emptyList()) to it.exceptionOrNull() + }.map { + when (it.second) { + // TODO(issue/296): remove when the CompilationStatusException is unified. + is CompilationStatusException -> + (it.second as CompilationStatusException).lines + it.first to it.second + else -> it + } + }.fold(Pair, Throwable?>(emptyList(), null)) { acc, result -> + acc.first + result.first to combine(acc.second, result.second) + }.apply { + first.apply(context::printCompilerOutput) + second?.let { + throw it } - }, - ).map { - (it.getOrNull() ?: emptyList()) to it.exceptionOrNull() - }.map { - when (it.second) { - // TODO(issue/296): remove when the CompilationStatusException is unified. - is CompilationStatusException -> - (it.second as CompilationStatusException).lines + it.first to it.second - else -> it - } - }.fold(Pair, Throwable?>(emptyList(), null)) { acc, result -> - acc.first + result.first to combine(acc.second, result.second) - }.apply { - first.apply(context::printCompilerOutput) - second?.let { - throw it } - } - if (outputs.jar.isNotEmpty()) { - if (instrumentCoverage) { - context.execute("create instrumented jar", ::createCoverageInstrumentedJar) - } else { - context.execute("create jar", ::createOutputJar) + if (outputs.jar.isNotEmpty()) { + if (instrumentCoverage) { + context.execute("create instrumented jar", ::createCoverageInstrumentedJar) + } else { + context.execute("create jar", ::createOutputJar) + } + } + if (outputs.abijar.isNotEmpty()) { + context.execute("create abi jar", ::createAbiJar) + } + if (outputs.generatedJavaSrcJar.isNotEmpty()) { + context.execute("creating KAPT generated Java source jar", ::createGeneratedJavaSrcJar) + } + if (outputs.generatedJavaStubJar.isNotEmpty()) { + context.execute("creating KAPT generated Kotlin stubs jar", ::createGeneratedStubJar) + } + if (outputs.generatedClassJar.isNotEmpty()) { + context.execute("creating KAPT generated stub class jar", ::createGeneratedClassJar) + } + if (outputs.generatedKspSrcJar.isNotEmpty()) { + context.execute("creating KSP generated src jar", ::createGeneratedKspKotlinSrcJar) } - } - if (outputs.abijar.isNotEmpty()) { - context.execute("create abi jar", ::createAbiJar) - } - if (outputs.generatedJavaSrcJar.isNotEmpty()) { - context.execute("creating KAPT generated Java source jar", ::createGeneratedJavaSrcJar) - } - if (outputs.generatedJavaStubJar.isNotEmpty()) { - context.execute("creating KAPT generated Kotlin stubs jar", ::createGeneratedStubJar) - } - if (outputs.generatedClassJar.isNotEmpty()) { - context.execute("creating KAPT generated stub class jar", ::createGeneratedClassJar) - } - if (outputs.generatedKspSrcJar.isNotEmpty()) { - context.execute("creating KSP generated src jar", ::createGeneratedKspKotlinSrcJar) } } } } -} diff --git a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/CompilationTaskContext.kt b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/CompilationTaskContext.kt index 93d8d852f..3676806da 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/CompilationTaskContext.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/CompilationTaskContext.kt @@ -28,8 +28,12 @@ import java.nio.file.FileSystems class CompilationTaskContext( val info: CompilationTaskInfo, private val out: PrintStream, - private val executionRoot: String = FileSystems.getDefault().getPath("").toAbsolutePath() - .toString() + File.separator, + private val executionRoot: String = + FileSystems + .getDefault() + .getPath("") + .toAbsolutePath() + .toString() + File.separator, ) { private val start = System.currentTimeMillis() private var timings: MutableList? @@ -75,18 +79,20 @@ class CompilationTaskContext( out.println() } - fun whenTracing(block: CompilationTaskContext.() -> T): T? { - return if (isTracing) { + fun whenTracing(block: CompilationTaskContext.() -> T): T? = + if (isTracing) { block() } else { null } - } /** * Print a proto message if debugging is enabled for the task. */ - fun printProto(header: String, msg: MessageOrBuilder) { + fun printProto( + header: String, + msg: MessageOrBuilder, + ) { printLines(header, TextFormat.printToString(msg).split("\n"), filterEmpty = true) } @@ -124,9 +130,10 @@ class CompilationTaskContext( val outputStream = ByteArrayOutputStream() val ps = PrintStream(outputStream) val result = compile(args.toTypedArray(), ps) - val output = ByteArrayInputStream(outputStream.toByteArray()) - .bufferedReader() - .readLines() + val output = + ByteArrayInputStream(outputStream.toByteArray()) + .bufferedReader() + .readLines() if (result != 0) { if (printOnFail) { printCompilerOutput(output) @@ -142,21 +149,29 @@ class CompilationTaskContext( /** * Runs a task and records the timings. */ - fun execute(name: String, task: () -> T): T = execute({ name }, task) + fun execute( + name: String, + task: () -> T, + ): T = execute({ name }, task) /** * Runs a task and records the timings. */ @Suppress("MemberVisibilityCanBePrivate") - fun execute(name: () -> String, task: () -> T): T { - return if (timings == null) { + fun execute( + name: () -> String, + task: () -> T, + ): T = + if (timings == null) { task() } else { pushTimedTask(name(), task) } - } - private inline fun pushTimedTask(name: String, task: () -> T): T { + private inline fun pushTimedTask( + name: String, + task: () -> T, + ): T { level += 1 val previousTimings = timings timings = mutableListOf() diff --git a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolException.kt b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolException.kt index 52b99539c..f84137ac7 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolException.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolException.kt @@ -20,8 +20,10 @@ sealed class KotlinToolException( ex: Throwable? = null, ) : RuntimeException(msg, ex) -class CompilationException(msg: String, cause: Throwable? = null) : - KotlinToolException(msg, cause) +class CompilationException( + msg: String, + cause: Throwable? = null, +) : KotlinToolException(msg, cause) class CompilationStatusException( msg: String, diff --git a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt index 7dff6432e..291377d16 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt @@ -40,66 +40,77 @@ class KotlinToolchain private constructor( val kspSymbolProcessingApi: CompilerPlugin, val kspSymbolProcessingCommandLine: CompilerPlugin, ) { - companion object { private val JVM_ABI_PLUGIN by lazy { - BazelRunFiles.resolveVerifiedFromProperty( - "@com_github_jetbrains_kotlin...jvm-abi-gen", - ).toPath() + BazelRunFiles + .resolveVerifiedFromProperty( + "@com_github_jetbrains_kotlin...jvm-abi-gen", + ).toPath() } private val KAPT_PLUGIN by lazy { - BazelRunFiles.resolveVerifiedFromProperty( - "@com_github_jetbrains_kotlin...kapt", - ).toPath() + BazelRunFiles + .resolveVerifiedFromProperty( + "@com_github_jetbrains_kotlin...kapt", + ).toPath() } private val COMPILER by lazy { - BazelRunFiles.resolveVerifiedFromProperty( - "@rules_kotlin...compiler", - ).toPath() + BazelRunFiles + .resolveVerifiedFromProperty( + "@rules_kotlin...compiler", + ).toPath() } private val SKIP_CODE_GEN_PLUGIN by lazy { - BazelRunFiles.resolveVerifiedFromProperty( - "@rules_kotlin...skip-code-gen", - ).toPath() + BazelRunFiles + .resolveVerifiedFromProperty( + "@rules_kotlin...skip-code-gen", + ).toPath() } private val JDEPS_GEN_PLUGIN by lazy { - BazelRunFiles.resolveVerifiedFromProperty( - "@rules_kotlin...jdeps-gen", - ).toPath() + BazelRunFiles + .resolveVerifiedFromProperty( + "@rules_kotlin...jdeps-gen", + ).toPath() } private val KOTLINC by lazy { - BazelRunFiles.resolveVerifiedFromProperty( - "@com_github_jetbrains_kotlin...kotlin-compiler", - ).toPath() + BazelRunFiles + .resolveVerifiedFromProperty( + "@com_github_jetbrains_kotlin...kotlin-compiler", + ).toPath() } private val KSP_SYMBOL_PROCESSING_API by lazy { - BazelRunFiles.resolveVerifiedFromProperty( - "@com_github_google_ksp...symbol-processing-api", - ).toPath() + BazelRunFiles + .resolveVerifiedFromProperty( + "@com_github_google_ksp...symbol-processing-api", + ).toPath() } private val KSP_SYMBOL_PROCESSING_CMDLINE by lazy { - BazelRunFiles.resolveVerifiedFromProperty( - "@com_github_google_ksp...symbol-processing-cmdline", - ).toPath() + BazelRunFiles + .resolveVerifiedFromProperty( + "@com_github_google_ksp...symbol-processing-cmdline", + ).toPath() } private val KOTLIN_REFLECT by lazy { - BazelRunFiles.resolveVerifiedFromProperty( - "@rules_kotlin..kotlin.compiler.kotlin-reflect", - ).toPath() + BazelRunFiles + .resolveVerifiedFromProperty( + "@rules_kotlin..kotlin.compiler.kotlin-reflect", + ).toPath() } private val JAVA_HOME by lazy { - FileSystems.getDefault().getPath(System.getProperty("java.home")).let { path -> - path.takeIf { !it.endsWith(Paths.get("jre")) } ?: path.parent - }.verifiedPath() + FileSystems + .getDefault() + .getPath(System.getProperty("java.home")) + .let { path -> + path.takeIf { !it.endsWith(Paths.get("jre")) } ?: path.parent + }.verifiedPath() } internal val NO_ARGS = arrayOf() @@ -107,8 +118,8 @@ class KotlinToolchain private constructor( private val isJdk9OrNewer = !System.getProperty("java.version").startsWith("1.") @JvmStatic - fun createToolchain(): KotlinToolchain { - return createToolchain( + fun createToolchain(): KotlinToolchain = + createToolchain( JAVA_HOME, KOTLINC.verified().absoluteFile, COMPILER.verified().absoluteFile, @@ -119,7 +130,6 @@ class KotlinToolchain private constructor( KSP_SYMBOL_PROCESSING_API.toFile(), KSP_SYMBOL_PROCESSING_CMDLINE.toFile(), ) - } @JvmStatic fun createToolchain( @@ -132,8 +142,8 @@ class KotlinToolchain private constructor( kaptFile: File, kspSymbolProcessingApi: File, kspSymbolProcessingCommandLine: File, - ): KotlinToolchain { - return KotlinToolchain( + ): KotlinToolchain = + KotlinToolchain( listOf( kotlinc, compiler, @@ -146,32 +156,37 @@ class KotlinToolchain private constructor( kspSymbolProcessingApi, kspSymbolProcessingCommandLine, ), - jvmAbiGen = CompilerPlugin( - jvmAbiGenFile.path, - "org.jetbrains.kotlin.jvm.abi", - ), - skipCodeGen = CompilerPlugin( - skipCodeGenFile.path, - "io.bazel.kotlin.plugin.SkipCodeGen", - ), - jdepsGen = CompilerPlugin( - jdepsGenFile.path, - "io.bazel.kotlin.plugin.jdeps.JDepsGen", - ), - kapt3Plugin = CompilerPlugin( - kaptFile.path, - "org.jetbrains.kotlin.kapt3", - ), - kspSymbolProcessingApi = CompilerPlugin( - kspSymbolProcessingApi.absolutePath, - "com.google.devtools.ksp.symbol-processing", - ), - kspSymbolProcessingCommandLine = CompilerPlugin( - kspSymbolProcessingCommandLine.absolutePath, - "com.google.devtools.ksp.symbol-processing", - ), + jvmAbiGen = + CompilerPlugin( + jvmAbiGenFile.path, + "org.jetbrains.kotlin.jvm.abi", + ), + skipCodeGen = + CompilerPlugin( + skipCodeGenFile.path, + "io.bazel.kotlin.plugin.SkipCodeGen", + ), + jdepsGen = + CompilerPlugin( + jdepsGenFile.path, + "io.bazel.kotlin.plugin.jdeps.JDepsGen", + ), + kapt3Plugin = + CompilerPlugin( + kaptFile.path, + "org.jetbrains.kotlin.kapt3", + ), + kspSymbolProcessingApi = + CompilerPlugin( + kspSymbolProcessingApi.absolutePath, + "com.google.devtools.ksp.symbol-processing", + ), + kspSymbolProcessingCommandLine = + CompilerPlugin( + kspSymbolProcessingCommandLine.absolutePath, + "com.google.devtools.ksp.symbol-processing", + ), ) - } } private fun createClassLoader( @@ -202,8 +217,8 @@ class KotlinToolchain private constructor( ) } - fun toolchainWithReflect(kotlinReflect: File? = null): KotlinToolchain { - return KotlinToolchain( + fun toolchainWithReflect(kotlinReflect: File? = null): KotlinToolchain = + KotlinToolchain( baseJars + listOf(kotlinReflect ?: KOTLIN_REFLECT.toFile()), kapt3Plugin, jvmAbiGen, @@ -212,9 +227,11 @@ class KotlinToolchain private constructor( kspSymbolProcessingApi, kspSymbolProcessingCommandLine, ) - } - data class CompilerPlugin(val jarPath: String, val id: String) + data class CompilerPlugin( + val jarPath: String, + val id: String, + ) open class KotlinCliToolInvoker internal constructor( toolchain: KotlinToolchain, @@ -239,25 +256,32 @@ class KotlinToolchain private constructor( // 1 is a standard compilation error // 2 is an internal error // 3 is the script execution error - fun compile(args: Array, out: PrintStream): Int { + fun compile( + args: Array, + out: PrintStream, + ): Int { val exitCodeInstance = execMethod.invoke(compiler, out, args) return getCodeMethod.invoke(exitCodeInstance, *NO_ARGS) as Int } } @Singleton - class KotlincInvoker @Inject constructor( - toolchain: KotlinToolchain, - ) : KotlinCliToolInvoker( - toolchain.toolchainWithReflect(), - "io.bazel.kotlin.compiler.BazelK2JVMCompiler", - ) + class KotlincInvoker + @Inject + constructor( + toolchain: KotlinToolchain, + ) : KotlinCliToolInvoker( + toolchain.toolchainWithReflect(), + "io.bazel.kotlin.compiler.BazelK2JVMCompiler", + ) @Singleton - class K2JSCompilerInvoker @Inject constructor( - toolchain: KotlinToolchain, - ) : KotlinCliToolInvoker( - toolchain.toolchainWithReflect(), - "org.jetbrains.kotlin.cli.js.K2JsIrCompiler", - ) + class K2JSCompilerInvoker + @Inject + constructor( + toolchain: KotlinToolchain, + ) : KotlinCliToolInvoker( + toolchain.toolchainWithReflect(), + "org.jetbrains.kotlin.cli.js.K2JsIrCompiler", + ) } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/ArgMap.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/ArgMap.kt index a3879fba8..09c0c400c 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/ArgMap.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/ArgMap.kt @@ -19,7 +19,9 @@ package io.bazel.kotlin.builder.utils import java.io.File -class ArgMap(private val map: Map>) { +class ArgMap( + private val map: Map>, +) { /** * Get the mandatory single value from a key */ @@ -43,38 +45,47 @@ class ArgMap(private val map: Map>) { } } - private fun optionalSingleIf(key: String, condition: () -> Boolean): String? { - return if (condition()) { + private fun optionalSingleIf( + key: String, + condition: () -> Boolean, + ): String? = + if (condition()) { optionalSingle(key) } else { mandatorySingle(key) } - } - private fun hasAll(keys: Array): Boolean { - return keys.all { optional(it)?.isNotEmpty() ?: false } - } + private fun hasAll(keys: Array): Boolean = + keys.all { optional(it)?.isNotEmpty() ?: false } - private fun hasAny(keys: Array): Boolean { - return keys.any { optional(it)?.isNotEmpty() ?: false } - } + private fun hasAny(keys: Array): Boolean = + keys.any { optional(it)?.isNotEmpty() ?: false } - private fun mandatory(key: String): List = optional(key) - ?: throw IllegalArgumentException( - "$key is not optional", - ) + private fun mandatory(key: String): List = + optional(key) + ?: throw IllegalArgumentException( + "$key is not optional", + ) private fun optional(key: String): List? = map[key] fun mandatorySingle(key: Flag) = mandatorySingle(key.flag) + fun optionalSingle(key: Flag) = optionalSingle(key.flag) - fun optionalSingleIf(key: Flag, condition: () -> Boolean) = - optionalSingleIf(key.flag, condition) + + fun optionalSingleIf( + key: Flag, + condition: () -> Boolean, + ) = optionalSingleIf(key.flag, condition) fun hasAll(vararg keys: Flag) = hasAll(keys.map(Flag::flag).toTypedArray()) + fun hasAny(vararg keys: Flag) = hasAny(keys.map(Flag::flag).toTypedArray()) + fun mandatory(key: Flag) = mandatory(key.flag) + fun optional(key: Flag) = optional(key.flag) + fun labelDepMap(key: Flag) = labelDepMap(key.flag) } @@ -104,13 +115,15 @@ object ArgMaps { argMap.computeIfAbsent(currentKey) { mutableListOf() }.addAll(currentValue) currentValue.clear() } - args.drop(1).forEach { - if (it.startsWith("--")) { - mergeCurrent() - currentKey = it - } else { - currentValue.add(it) - } - }.also { mergeCurrent() } + args + .drop(1) + .forEach { + if (it.startsWith("--")) { + mergeCurrent() + currentKey = it + } else { + currentValue.add(it) + } + }.also { mergeCurrent() } } } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/BazelRunFiles.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/BazelRunFiles.kt index 3003763de..080f4802b 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/BazelRunFiles.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/BazelRunFiles.kt @@ -21,7 +21,6 @@ import java.io.FileNotFoundException /** Utility class for getting runfiles on windows and *nix. */ object BazelRunFiles { - private val runfiles by lazy { Runfiles.preload().unmapped() } @@ -31,7 +30,8 @@ object BazelRunFiles { */ @JvmStatic fun resolveVerifiedFromProperty(key: String) = - System.getProperty(key) + System + .getProperty(key) ?.let { path -> runfiles.rlocation(path) } ?.let { File(it) } ?.also { diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/IOUtils.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/IOUtils.kt index f1bdaf33b..6fba97230 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/IOUtils.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/IOUtils.kt @@ -29,7 +29,10 @@ import java.util.Arrays import java.util.concurrent.TimeUnit import java.util.concurrent.TimeoutException -private fun executeAwait(timeoutSeconds: Int, process: Process): Int { +private fun executeAwait( + timeoutSeconds: Int, + process: Process, +): Int { try { if (!process.waitFor(timeoutSeconds.toLong(), TimeUnit.SECONDS)) { throw TimeoutException() @@ -42,13 +45,18 @@ private fun executeAwait(timeoutSeconds: Int, process: Process): Int { } } -fun executeAndAwait(timeoutSeconds: Int, directory: File? = null, args: List): Int { - val process = ProcessBuilder(*args.toTypedArray()).let { pb -> - pb.redirectError(ProcessBuilder.Redirect.PIPE) - pb.redirectOutput(ProcessBuilder.Redirect.PIPE) - directory?.also { pb.directory(it) } - pb.start() - } +fun executeAndAwait( + timeoutSeconds: Int, + directory: File? = null, + args: List, +): Int { + val process = + ProcessBuilder(*args.toTypedArray()).let { pb -> + pb.redirectError(ProcessBuilder.Redirect.PIPE) + pb.redirectOutput(ProcessBuilder.Redirect.PIPE) + directory?.also { pb.directory(it) } + pb.start() + } var isr: BufferedReader? = null var esr: BufferedReader? = null @@ -64,17 +72,21 @@ fun executeAndAwait(timeoutSeconds: Int, directory: File? = null, args: List> C.addAll(vararg entries: T): C = this.also { a /** * Utility function to add multiple entries to a list with a leader. */ -fun > C.addAll(leader: T, entries: List): C = - this.also { add(leader); addAll(entries) } +fun > C.addAll( + leader: T, + entries: List, +): C = + this.also { + add(leader) + addAll(entries) + } private fun extensionMatcher(vararg ext: String): Predicate = - Pattern.compile("^(.+?)${ext.joinToString("|\\.", prefix = "(\\.", postfix = ")$")}") + Pattern + .compile("^(.+?)${ext.joinToString("|\\.", prefix = "(\\.", postfix = ")$")}") .asPredicate() val IS_JVM_SOURCE_FILE = extensionMatcher("kt", "java") diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/TaskUtils.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/TaskUtils.kt index 18012a029..0f377fee9 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/TaskUtils.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/TaskUtils.kt @@ -20,14 +20,18 @@ import io.bazel.kotlin.model.JvmCompilationTask import java.io.File val JvmCompilationTask.Inputs.joinedClasspath: String - get() = this.classpathList.joinToString( - File.pathSeparator, - ) + get() = + this.classpathList.joinToString( + File.pathSeparator, + ) val CompilationTaskInfo.bazelRuleKind: String get() = "kt_${platform.name.lowercase()}_${ruleKind.name.lowercase()}" -fun Iterator.partitionJvmSources(kt: (String) -> Unit, java: (String) -> Unit) { +fun Iterator.partitionJvmSources( + kt: (String) -> Unit, + java: (String) -> Unit, +) { forEach { when { it.endsWith(".kt") -> kt(it) diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/WorkingDirectoryContext.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/WorkingDirectoryContext.kt index fb0963241..39fdd8657 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/WorkingDirectoryContext.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/WorkingDirectoryContext.kt @@ -22,11 +22,14 @@ import java.nio.file.Files import java.nio.file.Path /** WorkingDirectoryContext provides a consistent base directory that is removed on close. */ -class WorkingDirectoryContext(val dir: Path) : Closeable { +class WorkingDirectoryContext( + val dir: Path, +) : Closeable { companion object { - fun newContext(): WorkingDirectoryContext = WorkingDirectoryContext( - Files.createTempDirectory("working"), - ) + fun newContext(): WorkingDirectoryContext = + WorkingDirectoryContext( + Files.createTempDirectory("working"), + ) } override fun close() { diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarCreator.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarCreator.kt index 96f9da2ce..ad9bbabf4 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarCreator.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarCreator.kt @@ -41,7 +41,8 @@ class JarCreator( path: Path, normalize: Boolean = true, verbose: Boolean = false, -) : JarHelper(path, normalize, verbose), Closeable { +) : JarHelper(path, normalize, verbose), + Closeable { // Map from Jar entry names to files. Use TreeMap so we can establish a canonical order for the // entries regardless in what order they get added. private val jarEntries = TreeMap() @@ -57,7 +58,10 @@ class JarCreator( * @param path the path of the input for the entry * @return true iff a new entry was added */ - private fun addEntry(entryName: String, path: Path): Boolean { + private fun addEntry( + entryName: String, + path: Path, + ): Boolean { var normalizedEntryName = entryName if (normalizedEntryName.startsWith("/")) { normalizedEntryName = normalizedEntryName.substring(1) @@ -82,9 +86,10 @@ class JarCreator( * @param fileName the name of the input file for the entry * @return true iff a new entry was added */ - fun addEntry(entryName: String, fileName: String): Boolean { - return addEntry(entryName, get(fileName)) - } + fun addEntry( + entryName: String, + fileName: String, + ): Boolean = addEntry(entryName, get(fileName)) /** * Adds the contents of a directory to the Jar file. All files below this directory will be added @@ -100,9 +105,11 @@ class JarCreator( Files.walkFileTree( directory, object : SimpleFileVisitor() { - @Throws(IOException::class) - override fun preVisitDirectory(path: Path, attrs: BasicFileAttributes): FileVisitResult { + override fun preVisitDirectory( + path: Path, + attrs: BasicFileAttributes, + ): FileVisitResult { if (path != directory) { // For consistency with legacy behaviour, include entries for directories except for // the root. @@ -112,12 +119,18 @@ class JarCreator( } @Throws(IOException::class) - override fun visitFile(path: Path, attrs: BasicFileAttributes): FileVisitResult { + override fun visitFile( + path: Path, + attrs: BasicFileAttributes, + ): FileVisitResult { addEntry(path, isDirectory = false) return FileVisitResult.CONTINUE } - fun addEntry(path: Path, isDirectory: Boolean) { + fun addEntry( + path: Path, + isDirectory: Boolean, + ) { val sb = StringBuilder() var first = true for (entry in directory.relativize(path)) { @@ -165,7 +178,10 @@ class JarCreator( this.mainClass = mainClass } - fun setJarOwner(targetLabel: String, injectingRuleKind: String) { + fun setJarOwner( + targetLabel: String, + injectingRuleKind: String, + ) { this.targetLabel = targetLabel this.injectingRuleKind = injectingRuleKind } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarExtractor.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarExtractor.kt index 08b4be591..dcba24fc6 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarExtractor.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarExtractor.kt @@ -23,13 +23,15 @@ import java.util.jar.JarFile open class JarExtractor protected constructor( protected var destDir: Path, ) { - /** * @param isDirectory is the target a directory. * @param target path the operation will apply to. * @return weather the operation should be applied or not. */ - internal open fun preWrite(isDirectory: Boolean, target: Path): Boolean = true + internal open fun preWrite( + isDirectory: Boolean, + target: Path, + ): Boolean = true protected fun extract(jarFile: Path) { JarFile(jarFile.toFile()).use { jar -> @@ -41,10 +43,11 @@ open class JarExtractor protected constructor( when { entry.isDirectory -> Files.createDirectories(target) - else -> jar.getInputStream(entry).use { - Files.createDirectories(target.parent) - Files.copy(it, target, StandardCopyOption.REPLACE_EXISTING) - } + else -> + jar.getInputStream(entry).use { + Files.createDirectories(target.parent) + Files.copy(it, target, StandardCopyOption.REPLACE_EXISTING) + } } } } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarHelper.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarHelper.kt index abb4eaf6f..ce1d8a747 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarHelper.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarHelper.kt @@ -73,13 +73,12 @@ open class JarHelper internal constructor( * @param name The name of the file for which we should return the normalized timestamp. * @return the time for a new Jar file entry in milliseconds since the epoch. */ - private fun normalizedTimestamp(name: String): Long { - return if (name.endsWith(".class")) { + private fun normalizedTimestamp(name: String): Long = + if (name.endsWith(".class")) { DEFAULT_TIMESTAMP + MINIMUM_TIMESTAMP_INCREMENT } else { DEFAULT_TIMESTAMP } - } /** * Returns the time for a new Jar file entry in milliseconds since the epoch. Uses JarCreator.DEFAULT_TIMESTAMP] @@ -88,16 +87,19 @@ open class JarHelper internal constructor( * @param filename The name of the file for which we are entering the time * @return the time for a new Jar file entry in milliseconds since the epoch. */ - private fun newEntryTimeMillis(filename: String): Long { - return if (normalize) normalizedTimestamp(filename) else System.currentTimeMillis() - } + private fun newEntryTimeMillis(filename: String): Long = + if (normalize) normalizedTimestamp(filename) else System.currentTimeMillis() /** * Writes an entry with specific contents to the jar. Directory entries must include the trailing * '/'. */ @Throws(IOException::class) - private fun writeEntry(out: JarOutputStream, name: String, content: ByteArray) { + private fun writeEntry( + out: JarOutputStream, + name: String, + content: ByteArray, + ) { if (names.add(name)) { // Create a new entry val entry = JarEntry(name) @@ -130,7 +132,10 @@ open class JarHelper internal constructor( * @throws IOException */ @Throws(IOException::class) - protected fun writeManifestEntry(out: JarOutputStream, content: ByteArray) { + protected fun writeManifestEntry( + out: JarOutputStream, + content: ByteArray, + ) { val oldStorageMethod = storageMethod // Do not compress small manifest files, the compressed one is frequently // larger than the original. The threshold of 256 bytes is somewhat arbitrary. @@ -150,7 +155,10 @@ open class JarHelper internal constructor( * detected and their names automatically '/' suffixed. */ @Throws(IOException::class) - protected fun JarOutputStream.copyEntry(name: String, path: Path) { + protected fun JarOutputStream.copyEntry( + name: String, + path: Path, + ) { var normalizedName = name if (!names.contains(normalizedName)) { if (!Files.exists(path)) { @@ -171,7 +179,8 @@ open class JarHelper internal constructor( if (normalize) { normalizedTimestamp(normalizedName) } else { - Files.getLastModifiedTime(path) + Files + .getLastModifiedTime(path) .toMillis() } outEntry.time = newtime @@ -217,10 +226,11 @@ open class JarHelper internal constructor( data: ByteArray = EMPTY_BYTEARRAY, ) { val outEntry = JarEntry(name) - outEntry.time = when { - normalize -> normalizedTimestamp(name) - else -> Files.getLastModifiedTime(checkNotNull(path)).toMillis() - } + outEntry.time = + when { + normalize -> normalizedTimestamp(name) + else -> Files.getLastModifiedTime(checkNotNull(path)).toMillis() + } outEntry.size = data.size.toLong() if (data.isEmpty()) { diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarOwner.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarOwner.kt index 2f98b7d16..8dc3687b9 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarOwner.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/JarOwner.kt @@ -7,15 +7,20 @@ import java.io.UncheckedIOException import java.nio.file.Path import java.util.jar.JarFile -data class JarOwner(val jar: Path, val label: String? = null, val aspect: String? = null) { +data class JarOwner( + val jar: Path, + val label: String? = null, + val aspect: String? = null, +) { companion object { fun readJarOwnerFromManifest(jarPath: Path): JarOwner { try { JarFile(jarPath.toFile()).use { jarFile -> val manifest = jarFile.manifest ?: return JarOwner(jarPath) val attributes = manifest.mainAttributes - val label = attributes[TARGET_LABEL] as String? - ?: return JarOwner(jarPath) + val label = + attributes[TARGET_LABEL] as String? + ?: return JarOwner(jarPath) val injectingRuleKind = attributes[INJECTING_RULE_KIND] as String? return JarOwner(jarPath, label, injectingRuleKind) } diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/SourceJarCreator.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/SourceJarCreator.kt index 5e61bfaa7..1ae9306e1 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/SourceJarCreator.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/SourceJarCreator.kt @@ -41,13 +41,15 @@ class SourceJarCreator( fun extractPackage(line: String): String? = PKG_PATTERN.matcher(line).takeIf { it.matches() }?.group(1) - private fun isJavaSourceLike(name: String): Boolean { - return name.endsWith(".kt") || name.endsWith(".java") - } + private fun isJavaSourceLike(name: String): Boolean = + name.endsWith(".kt") || name.endsWith(".java") } sealed class Entry { - class File(val path: Path, val content: ByteArray) : Entry() { + class File( + val path: Path, + val content: ByteArray, + ) : Entry() { override fun toString(): String = "File $path" } @@ -75,7 +77,10 @@ class SourceJarCreator( * Files like `package-info.java` could end up getting deferred if they have an annotation embedded on the same * line or files that have entries such as `/* weird comment */package lala` */ - fun getFilenameOrDefer(sourceFile: Path, body: ByteArray): String? = + fun getFilenameOrDefer( + sourceFile: Path, + body: ByteArray, + ): String? = directoryToPackageMap[sourceFile.parent] ?: locatePackagePathOrDefer(sourceFile, body)?.let { "$it/${sourceFile.fileName}" } @@ -91,14 +96,20 @@ class SourceJarCreator( } } - private fun locatePackagePathOrDefer(sourceFile: Path, body: ByteArray): String? = - body.inputStream().bufferedReader().useLines { - it.mapNotNull(::extractPackage).firstOrNull()?.replace('.', '/') - }.also { - if (it == null) { - deferredEntries[sourceFile] = body + private fun locatePackagePathOrDefer( + sourceFile: Path, + body: ByteArray, + ): String? = + body + .inputStream() + .bufferedReader() + .useLines { + it.mapNotNull(::extractPackage).firstOrNull()?.replace('.', '/') + }.also { + if (it == null) { + deferredEntries[sourceFile] = body + } } - } } private val filenameHelper = JarFilenameHelper() @@ -182,7 +193,11 @@ class SourceJarCreator( } } - private fun addEntry(name: String, path: Path, bytes: ByteArray) { + private fun addEntry( + name: String, + path: Path, + bytes: ByteArray, + ) { name.split("/").also { if (it.size >= 2) { for (i in ((it.size - 1) downTo 1)) { diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/SourceJarExtractor.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/SourceJarExtractor.kt index 7039837fb..f9fd42dec 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/SourceJarExtractor.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/jars/SourceJarExtractor.kt @@ -18,12 +18,17 @@ package io.bazel.kotlin.builder.utils.jars import java.nio.file.Path import java.util.function.Predicate -class SourceJarExtractor(destDir: Path, val fileMatcher: Predicate = Predicate { true }) : - JarExtractor(destDir) { +class SourceJarExtractor( + destDir: Path, + val fileMatcher: Predicate = Predicate { true }, +) : JarExtractor(destDir) { val jarFiles = mutableListOf() val sourcesList = mutableListOf() - override fun preWrite(isDirectory: Boolean, target: Path): Boolean { + override fun preWrite( + isDirectory: Boolean, + target: Path, + ): Boolean { if (isDirectory) { return true } diff --git a/src/main/kotlin/io/bazel/kotlin/compiler/BazelK2JVMCompiler.kt b/src/main/kotlin/io/bazel/kotlin/compiler/BazelK2JVMCompiler.kt index 26819e118..f42c2da1f 100644 --- a/src/main/kotlin/io/bazel/kotlin/compiler/BazelK2JVMCompiler.kt +++ b/src/main/kotlin/io/bazel/kotlin/compiler/BazelK2JVMCompiler.kt @@ -23,7 +23,10 @@ import org.jetbrains.kotlin.config.Services @Suppress("unused") class BazelK2JVMCompiler { - fun exec(errStream: java.io.PrintStream, vararg args: String): ExitCode { + fun exec( + errStream: java.io.PrintStream, + vararg args: String, + ): ExitCode { System.setProperty("zip.handler.uses.crc.instead.of.timestamp", "true") val delegate: K2JVMCompiler = K2JVMCompiler() val arguments = delegate.createArguments().also { delegate.parseArguments(args, it) } diff --git a/src/main/kotlin/io/bazel/kotlin/plugin/SkipCodeGen.kt b/src/main/kotlin/io/bazel/kotlin/plugin/SkipCodeGen.kt index 5254b9ae4..16a14be4a 100644 --- a/src/main/kotlin/io/bazel/kotlin/plugin/SkipCodeGen.kt +++ b/src/main/kotlin/io/bazel/kotlin/plugin/SkipCodeGen.kt @@ -33,7 +33,6 @@ import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension */ @OptIn(org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi::class) class SkipCodeGen : CompilerPluginRegistrar() { - override val supportsK2: Boolean get() = false @@ -49,7 +48,6 @@ class SkipCodeGen : CompilerPluginRegistrar() { * SkipCodeGen ends the compilation */ private object SkipCodeGen : AnalysisHandlerExtension { - override fun doAnalysis( project: Project, module: ModuleDescriptor, @@ -57,9 +55,7 @@ class SkipCodeGen : CompilerPluginRegistrar() { files: Collection, bindingTrace: BindingTrace, componentProvider: ComponentProvider, - ): AnalysisResult? { - return null - } + ): AnalysisResult? = null // analysisCompleted generates the module jvm abi and requests code generation to be skipped. override fun analysisCompleted( diff --git a/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/BaseJdepsGenExtension.kt b/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/BaseJdepsGenExtension.kt index df08ee406..a1f4e47f1 100644 --- a/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/BaseJdepsGenExtension.kt +++ b/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/BaseJdepsGenExtension.kt @@ -10,7 +10,6 @@ import java.nio.file.Paths abstract class BaseJdepsGenExtension( protected val configuration: CompilerConfiguration, ) { - protected fun onAnalysisCompleted( explicitClassesCanonicalPaths: Set, implicitClassesCanonicalPaths: Set, @@ -107,9 +106,10 @@ abstract class BaseJdepsGenExtension( directDeps: List, targetLabel: String, ): Boolean { - val missingStrictDeps = result.keys - .filter { !directDeps.contains(it) } - .map { JarOwner.readJarOwnerFromManifest(Paths.get(it)) } + val missingStrictDeps = + result.keys + .filter { !directDeps.contains(it) } + .map { JarOwner.readJarOwnerFromManifest(Paths.get(it)) } if (missingStrictDeps.isNotEmpty()) { val missingStrictLabels = missingStrictDeps.mapNotNull { it.label } diff --git a/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenCommandLineProcessor.kt b/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenCommandLineProcessor.kt index 122dab2a3..78f68b0bb 100644 --- a/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenCommandLineProcessor.kt +++ b/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenCommandLineProcessor.kt @@ -31,12 +31,13 @@ class JdepsGenCommandLineProcessor : CommandLineProcessor { override val pluginId: String get() = COMPILER_PLUGIN_ID override val pluginOptions: Collection - get() = listOf( - OUTPUT_JDEPS_FILE_OPTION, - TARGET_LABEL_OPTION, - DIRECT_DEPENDENCIES_OPTION, - STRICT_KOTLIN_DEPS_OPTION, - ) + get() = + listOf( + OUTPUT_JDEPS_FILE_OPTION, + TARGET_LABEL_OPTION, + DIRECT_DEPENDENCIES_OPTION, + STRICT_KOTLIN_DEPS_OPTION, + ) override fun processOption( option: AbstractCliOption, @@ -46,14 +47,16 @@ class JdepsGenCommandLineProcessor : CommandLineProcessor { when (option) { OUTPUT_JDEPS_FILE_OPTION -> configuration.put(JdepsGenConfigurationKeys.OUTPUT_JDEPS, value) TARGET_LABEL_OPTION -> configuration.put(JdepsGenConfigurationKeys.TARGET_LABEL, value) - DIRECT_DEPENDENCIES_OPTION -> configuration.appendList( - JdepsGenConfigurationKeys.DIRECT_DEPENDENCIES, - value, - ) - STRICT_KOTLIN_DEPS_OPTION -> configuration.put( - JdepsGenConfigurationKeys.STRICT_KOTLIN_DEPS, - value, - ) + DIRECT_DEPENDENCIES_OPTION -> + configuration.appendList( + JdepsGenConfigurationKeys.DIRECT_DEPENDENCIES, + value, + ) + STRICT_KOTLIN_DEPS_OPTION -> + configuration.put( + JdepsGenConfigurationKeys.STRICT_KOTLIN_DEPS, + value, + ) else -> throw CliOptionProcessingException("Unknown option: ${option.optionName}") } } diff --git a/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenComponentRegistrar.kt b/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenComponentRegistrar.kt index 35948ebb9..be5420a9a 100644 --- a/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenComponentRegistrar.kt +++ b/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenComponentRegistrar.kt @@ -7,7 +7,6 @@ import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension @OptIn(org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi::class) class JdepsGenComponentRegistrar : CompilerPluginRegistrar() { - override val supportsK2: Boolean get() = false diff --git a/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenExtension.kt b/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenExtension.kt index 8e498e66f..ecbf61b59 100644 --- a/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenExtension.kt +++ b/src/main/kotlin/io/bazel/kotlin/plugin/jdeps/JdepsGenExtension.kt @@ -69,9 +69,7 @@ class JdepsGenExtension( ) : BaseJdepsGenExtension(configuration), AnalysisHandlerExtension, StorageComponentContainerContributor { - companion object { - /** * Returns the path of the jar archive file corresponding to the provided descriptor. * @@ -80,19 +78,20 @@ class JdepsGenExtension( */ fun getClassCanonicalPath(descriptor: DeclarationDescriptorWithSource): String? { // Get the descriptor's source element which may be a type alias - val sourceElement = if (descriptor.source != SourceElement.NO_SOURCE) { - descriptor.source - } else { - when (val declarationDescriptor = descriptor.getImportableDescriptor()) { - is DeserializedTypeAliasDescriptor -> { - declarationDescriptor.containerSource - } + val sourceElement = + if (descriptor.source != SourceElement.NO_SOURCE) { + descriptor.source + } else { + when (val declarationDescriptor = descriptor.getImportableDescriptor()) { + is DeserializedTypeAliasDescriptor -> { + declarationDescriptor.containerSource + } - else -> { - null + else -> { + null + } } } - } return when (sourceElement) { is JavaSourceElement -> @@ -123,13 +122,12 @@ class JdepsGenExtension( } } - private fun getClassCanonicalPath(typeConstructor: TypeConstructor): String? { - return (typeConstructor.declarationDescriptor as? DeclarationDescriptorWithSource)?.let { + private fun getClassCanonicalPath(typeConstructor: TypeConstructor): String? = + (typeConstructor.declarationDescriptor as? DeclarationDescriptorWithSource)?.let { getClassCanonicalPath( it, ) } - } } private val explicitClassesCanonicalPaths = mutableSetOf() @@ -148,8 +146,8 @@ class JdepsGenExtension( class ClasspathCollectingChecker( private val explicitClassesCanonicalPaths: MutableSet, private val implicitClassesCanonicalPaths: MutableSet, - ) : CallChecker, DeclarationChecker { - + ) : CallChecker, + DeclarationChecker { override fun check( resolvedCall: ResolvedCall<*>, reportOn: PsiElement, @@ -187,15 +185,14 @@ class JdepsGenExtension( ( resultingDescriptor.getter ?.correspondingProperty as? SyntheticJavaPropertyDescriptor - ) - ?.let { syntheticJavaPropertyDescriptor -> - collectTypeReferences(syntheticJavaPropertyDescriptor.type, isExplicit = false) + )?.let { syntheticJavaPropertyDescriptor -> + collectTypeReferences(syntheticJavaPropertyDescriptor.type, isExplicit = false) - val functionDescriptor = syntheticJavaPropertyDescriptor.getMethod - functionDescriptor.dispatchReceiverParameter?.type?.let { dispatchReceiverType -> - collectTypeReferences(dispatchReceiverType, isExplicit = false) - } + val functionDescriptor = syntheticJavaPropertyDescriptor.getMethod + functionDescriptor.dispatchReceiverParameter?.type?.let { dispatchReceiverType -> + collectTypeReferences(dispatchReceiverType, isExplicit = false) } + } } } @@ -216,14 +213,18 @@ class JdepsGenExtension( } private fun collectExplicitTypes(resolvedCall: ResolvedCall<*>) { - val kotlinCallArguments = (resolvedCall as? NewAbstractResolvedCall) - ?.resolvedCallAtom?.atom?.argumentsInParenthesis + val kotlinCallArguments = + (resolvedCall as? NewAbstractResolvedCall) + ?.resolvedCallAtom + ?.atom + ?.argumentsInParenthesis // note that callArgument can be both a PSIKotlinCallArgument and an ExpressionKotlinCallArgument kotlinCallArguments?.forEach { callArgument -> if (callArgument is PSIKotlinCallArgument) { - val dataFlowInfos = listOf(callArgument.dataFlowInfoBeforeThisArgument) + - callArgument.dataFlowInfoAfterThisArgument + val dataFlowInfos = + listOf(callArgument.dataFlowInfoBeforeThisArgument) + + callArgument.dataFlowInfoAfterThisArgument dataFlowInfos.forEach { dataFlowInfo -> dataFlowInfo.completeTypeInfo.values().flatten().forEach { kotlinType -> diff --git a/src/main/kotlin/io/bazel/worker/ContextLog.kt b/src/main/kotlin/io/bazel/worker/ContextLog.kt index edcc0b0fb..617beda19 100644 --- a/src/main/kotlin/io/bazel/worker/ContextLog.kt +++ b/src/main/kotlin/io/bazel/worker/ContextLog.kt @@ -25,14 +25,15 @@ import java.util.logging.Level data class ContextLog( val out: CharSequence, val profiles: List = emptyList(), -) : - CharSequence by out { +) : CharSequence by out { constructor( bytes: ByteArray, profiles: List, ) : this(String(bytes, UTF_8), profiles) - enum class Granularity(val level: Level) { + enum class Granularity( + val level: Level, + ) { INFO(Level.INFO), ERROR(Level.SEVERE), DEBUG(Level.FINEST), @@ -41,7 +42,9 @@ data class ContextLog( /** Logging runtime messages lazily */ interface Logging { fun debug(msg: () -> String) + fun info(msg: () -> String) + fun error( t: Throwable, msg: () -> String, @@ -56,7 +59,9 @@ data class ContextLog( } /** ScopeLogging runtime messages to a namespace. */ - internal interface ScopeLogging : Summarize, Logging { + internal interface ScopeLogging : + Summarize, + Logging { fun narrowTo(name: String): ScopeLogging /** asPrintStream allows direct writing for backwards compatiblity. */ diff --git a/src/main/kotlin/io/bazel/worker/CpuTimeBasedGcScheduler.kt b/src/main/kotlin/io/bazel/worker/CpuTimeBasedGcScheduler.kt index 9c8e1fdfa..e4983f888 100644 --- a/src/main/kotlin/io/bazel/worker/CpuTimeBasedGcScheduler.kt +++ b/src/main/kotlin/io/bazel/worker/CpuTimeBasedGcScheduler.kt @@ -14,7 +14,6 @@ class CpuTimeBasedGcScheduler( */ private val cpuUsageBeforeGc: Duration, ) : GcScheduler { - /** The total process CPU time at the last GC run (or from the start of the worker). */ private val cpuTime: Duration get() = if (cpuUsageBeforeGc.isZero) Duration.ZERO else Duration.ofNanos(bean.processCpuTime) diff --git a/src/main/kotlin/io/bazel/worker/IO.kt b/src/main/kotlin/io/bazel/worker/IO.kt index 24fe5feb4..9d899df5c 100644 --- a/src/main/kotlin/io/bazel/worker/IO.kt +++ b/src/main/kotlin/io/bazel/worker/IO.kt @@ -32,7 +32,6 @@ class IO( private val captured: CapturingOutputStream, private val restore: () -> Unit = {}, ) : Closeable { - /** * Reads the captured std out and err as a UTF-8 string and then resets the * captured ByteArrayOutputStream. @@ -70,9 +69,10 @@ class IO( } class CapturingOutputStream : OutputStream() { - private val backing = object : ThreadLocal() { - override fun initialValue(): ByteArrayOutputStream = ByteArrayOutputStream() - } + private val backing = + object : ThreadLocal() { + override fun initialValue(): ByteArrayOutputStream = ByteArrayOutputStream() + } override fun write(b: Int) { backing.get().write(b) diff --git a/src/main/kotlin/io/bazel/worker/InvocationWorker.kt b/src/main/kotlin/io/bazel/worker/InvocationWorker.kt index 991edec33..63a4fa803 100644 --- a/src/main/kotlin/io/bazel/worker/InvocationWorker.kt +++ b/src/main/kotlin/io/bazel/worker/InvocationWorker.kt @@ -18,7 +18,9 @@ package io.bazel.worker /** InvocationWorker executes a single unit of work. */ -class InvocationWorker(private val arguments: Iterable) : Worker { +class InvocationWorker( + private val arguments: Iterable, +) : Worker { override fun start(execute: Work): Int = runCatching { WorkerContext.run { diff --git a/src/main/kotlin/io/bazel/worker/PersistentWorker.kt b/src/main/kotlin/io/bazel/worker/PersistentWorker.kt index 1245d3916..20d02c83f 100644 --- a/src/main/kotlin/io/bazel/worker/PersistentWorker.kt +++ b/src/main/kotlin/io/bazel/worker/PersistentWorker.kt @@ -43,7 +43,6 @@ class PersistentWorker( private val executor: ExecutorService, private val cpuTimeBasedGcScheduler: GcScheduler, ) : Worker { - constructor( executor: ExecutorService, captureIO: () -> IO, @@ -59,64 +58,70 @@ class PersistentWorker( CpuTimeBasedGcScheduler(Duration.ofSeconds(10)), ) - override fun start(execute: Work) = WorkerContext.run { - captureIO().use { io -> - val running = AtomicLong(0) - val completion = ExecutorCompletionService(executor) - val producer = executor.submit { - io.input.readRequestAnd { request -> - running.incrementAndGet() - completion.submit { - doTask( - name = "request ${request.requestId}", - task = request.workTo(execute), - ).asResponseTo(request.requestId, io) + override fun start(execute: Work) = + WorkerContext.run { + captureIO().use { io -> + val running = AtomicLong(0) + val completion = ExecutorCompletionService(executor) + val producer = + executor.submit { + io.input.readRequestAnd { request -> + running.incrementAndGet() + completion.submit { + doTask( + name = "request ${request.requestId}", + task = request.workTo(execute), + ).asResponseTo(request.requestId, io) + } + } } - } - } - val consumer = executor.submit { - while (!producer.isDone || running.get() > 0) { - // poll time is how long before checking producer liveliness. Too long, worker hangs - // when being shutdown -- too short, and it starves the process. - completion.poll(1, TimeUnit.SECONDS)?.run { - running.decrementAndGet() - get().writeDelimitedTo(io.output) - io.output.flush() + val consumer = + executor.submit { + while (!producer.isDone || running.get() > 0) { + // poll time is how long before checking producer liveliness. Too long, worker hangs + // when being shutdown -- too short, and it starves the process. + completion.poll(1, TimeUnit.SECONDS)?.run { + running.decrementAndGet() + get().writeDelimitedTo(io.output) + io.output.flush() + } + cpuTimeBasedGcScheduler.maybePerformGc() + } } - cpuTimeBasedGcScheduler.maybePerformGc() - } + producer.get() + consumer.get() + io.output.close() } - producer.get() - consumer.get() - io.output.close() + return@run 0 } - return@run 0 - } - private fun WorkRequest.workTo(execute: Work): (sub: WorkerContext.TaskContext) -> Status { - return { ctx -> execute(ctx, argumentsList.toList()) } - } + private fun WorkRequest.workTo(execute: Work): (sub: WorkerContext.TaskContext) -> Status = + { ctx -> execute(ctx, argumentsList.toList()) } private fun InputStream.readRequestAnd(action: (WorkRequest) -> Unit) { while (true) { - WorkRequest.parseDelimitedFrom(this) + WorkRequest + .parseDelimitedFrom(this) ?.run(action) ?: return } } - private fun TaskResult.asResponseTo(id: Int, io: IO): WorkResponse { - return WorkResponse.newBuilder() + private fun TaskResult.asResponseTo( + id: Int, + io: IO, + ): WorkResponse = + WorkResponse + .newBuilder() .apply { val cap = io.readCapturedAsUtf8String() // append whatever falls through standard out. - output = listOf( - log.out.toString(), - cap, - ).joinToString("\n").trim() + output = + listOf( + log.out.toString(), + cap, + ).joinToString("\n").trim() exitCode = status.exit requestId = id - } - .build() - } + }.build() } diff --git a/src/main/kotlin/io/bazel/worker/Status.kt b/src/main/kotlin/io/bazel/worker/Status.kt index 8213a7ba3..13852b44a 100644 --- a/src/main/kotlin/io/bazel/worker/Status.kt +++ b/src/main/kotlin/io/bazel/worker/Status.kt @@ -18,7 +18,9 @@ package io.bazel.worker /** Status for the Result of Work. */ -enum class Status(val exit: Int) { +enum class Status( + val exit: Int, +) { ERROR(1), SUCCESS(0), } diff --git a/src/main/kotlin/io/bazel/worker/Worker.kt b/src/main/kotlin/io/bazel/worker/Worker.kt index 0f668b63b..6be159ac3 100644 --- a/src/main/kotlin/io/bazel/worker/Worker.kt +++ b/src/main/kotlin/io/bazel/worker/Worker.kt @@ -24,10 +24,11 @@ interface Worker { args: Iterable, then: Worker.(Iterable) -> Int, ): Int { - val worker = when { - "--persistent_worker" in args -> PersistentWorker() - else -> InvocationWorker(args) - } + val worker = + when { + "--persistent_worker" in args -> PersistentWorker() + else -> InvocationWorker(args) + } return worker.then(args.filter { it != "--persistent_worker" }) } } diff --git a/src/main/kotlin/io/bazel/worker/WorkerContext.kt b/src/main/kotlin/io/bazel/worker/WorkerContext.kt index f913cbff0..5d60dc071 100644 --- a/src/main/kotlin/io/bazel/worker/WorkerContext.kt +++ b/src/main/kotlin/io/bazel/worker/WorkerContext.kt @@ -35,21 +35,20 @@ import java.util.logging.StreamHandler class WorkerContext private constructor( private val name: String = Companion::class.java.canonicalName, private val verbose: Granularity = INFO, -) : Closeable, ScopeLogging by ContextLogger(name, verbose.level, null) { - +) : Closeable, + ScopeLogging by ContextLogger(name, verbose.level, null) { companion object { fun run( named: String = "worker", verbose: Granularity = INFO, report: (ContextLog) -> Unit = {}, work: WorkerContext.() -> T, - ): T { - return WorkerContext(verbose = verbose, name = named).run { + ): T = + WorkerContext(verbose = verbose, name = named).run { use(work).also { report(contents()) } } - } } private class ContextLogger( @@ -57,7 +56,6 @@ class WorkerContext private constructor( val level: Level, val propagateTo: ContextLogger? = null, ) : ScopeLogging { - private val profiles = mutableListOf() private val out by lazy { @@ -101,9 +99,7 @@ class WorkerContext private constructor( logger.logp(Level.FINE, sourceName, name, msg) } - override fun narrowTo(name: String): ScopeLogging { - return ContextLogger(name, level, this) - } + override fun narrowTo(name: String): ScopeLogging = ContextLogger(name, level, this) override fun contents() = handler.flush().run { ContextLog(out.toByteArray(), profiles) } @@ -117,9 +113,7 @@ class WorkerContext private constructor( fun subTask( name: String = javaClass.canonicalName, task: (sub: TaskContext) -> T, - ): T { - return task(TaskContext(directory, logging = narrowTo(name))) - } + ): T = task(TaskContext(directory, logging = narrowTo(name))) /** resultOf a status supplier that includes information collected in the Context. */ fun resultOf(executeTaskIn: (TaskContext) -> Status): TaskResult { @@ -152,11 +146,12 @@ class WorkerContext private constructor( task: (sub: TaskContext) -> Status, ): TaskResult { info { "start task $name" } - return WorkingDirectoryContext.use { - TaskContext(dir, logging = narrowTo(name)).resultOf(task) - }.also { - info { "end task $name: ${it.status}" } - } + return WorkingDirectoryContext + .use { + TaskContext(dir, logging = narrowTo(name)).resultOf(task) + }.also { + info { "end task $name: ${it.status}" } + } } override fun close() { diff --git a/src/main/kotlin/io/bazel/worker/WorkingDirectoryContext.kt b/src/main/kotlin/io/bazel/worker/WorkingDirectoryContext.kt index b3bb37783..0f24443a0 100644 --- a/src/main/kotlin/io/bazel/worker/WorkingDirectoryContext.kt +++ b/src/main/kotlin/io/bazel/worker/WorkingDirectoryContext.kt @@ -24,10 +24,12 @@ import java.util.logging.Level import java.util.logging.Logger /** WorkingDirectoryContext provides a consistent base directory that is removed on close. */ -class WorkingDirectoryContext(val dir: Path) : Closeable { - +class WorkingDirectoryContext( + val dir: Path, +) : Closeable { companion object { val logger: Logger = Logger.getLogger(WorkingDirectoryContext::class.java.canonicalName) + inline fun use(forWork: WorkingDirectoryContext.() -> T) = WorkingDirectoryContext(Files.createTempDirectory("pwd")).use { wd -> wd.forWork() @@ -35,10 +37,11 @@ class WorkingDirectoryContext(val dir: Path) : Closeable { } override fun close() { - kotlin.runCatching { - Files.walk(dir).sorted(Comparator.reverseOrder()).forEach(Files::delete) - }.onFailure { - logger.log(Level.SEVERE, "Directory cleanup failed.", it) - } + kotlin + .runCatching { + Files.walk(dir).sorted(Comparator.reverseOrder()).forEach(Files::delete) + }.onFailure { + logger.log(Level.SEVERE, "Directory cleanup failed.", it) + } } } diff --git a/src/main/starlark/core/repositories/versions.bzl b/src/main/starlark/core/repositories/versions.bzl index d9f5df441..954b0aaed 100644 --- a/src/main/starlark/core/repositories/versions.bzl +++ b/src/main/starlark/core/repositories/versions.bzl @@ -54,11 +54,11 @@ versions = struct( ], ), PINTEREST_KTLINT = version( - version = "0.49.1", + version = "1.3.0", url_templates = [ "https://github.com/pinterest/ktlint/releases/download/{version}/ktlint", ], - sha256 = "2b3f6f674a944d25bb8d283c3539947bbe86074793012909a55de4b771f74bcc", + sha256 = "01b2e0ef893383a50dbeb13970fe7fa3be36ca3e83259e01649945b09d736985", ), KOTLIN_CURRENT_COMPILER_RELEASE = version( version = "1.9.23",