From a67382fdec28083ea8888dcf63d53df7ebbdfd3e Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Fri, 21 Apr 2017 13:51:41 +0300 Subject: [PATCH] Daemon: do not exit with internal error on invalid arguments Invalid compiler arguments should lead to a compilation error, not internal error. This has been fixed by splitting the "parseArguments(...)" call (which does parsing + validation) in CompileServiceImpl into two calls of parseCommandLineArguments + validateArguments, and returning with a compilation error if the latter did not succeed #KT-16057 Fixed #KT-14848 In Progress --- .../arguments/parseCommandLineArguments.kt | 2 +- .../jetbrains/kotlin/cli/common/CLITool.kt | 2 +- .../jetbrains/kotlin/cli/js/K2JSCompiler.java | 2 +- .../kotlin/daemon/CompileServiceImpl.kt | 57 +++++++------------ .../org/jetbrains/kotlin/utils/jvmUtils.kt | 27 --------- 5 files changed, 23 insertions(+), 67 deletions(-) delete mode 100644 compiler/util/src/org/jetbrains/kotlin/utils/jvmUtils.kt diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/parseCommandLineArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/parseCommandLineArguments.kt index d60948347c3..309e035ec85 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/parseCommandLineArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/parseCommandLineArguments.kt @@ -49,7 +49,7 @@ data class ArgumentParseErrors( var argumentWithoutValue: String? = null ) -// Parses arguments in the passed [result] object, or throws an [IllegalArgumentException] with the message to be displayed to the user +// Parses arguments into the passed [result] object. Errors related to the parsing will be collected into [CommonToolArguments.errors]. fun parseCommandLineArguments(args: Array, result: A) { data class ArgumentField(val field: Field, val argument: Argument) diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLITool.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLITool.kt index d0e54b0b5b2..ceda801e555 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLITool.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLITool.kt @@ -106,7 +106,7 @@ abstract class CLITool { } } - protected abstract fun createArguments(): A + abstract fun createArguments(): A // Used in kotlin-maven-plugin (KotlinCompileMojoBase) and in kotlin-gradle-plugin (KotlinJvmOptionsImpl, KotlinJsOptionsImpl) fun parseArguments(args: Array, arguments: A) { diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/js/K2JSCompiler.java b/compiler/cli/src/org/jetbrains/kotlin/cli/js/K2JSCompiler.java index c905b388a34..4a7ee43cb12 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/js/K2JSCompiler.java +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/js/K2JSCompiler.java @@ -82,7 +82,7 @@ public class K2JSCompiler extends CLICompiler { @NotNull @Override - protected K2JSCompilerArguments createArguments() { + public K2JSCompilerArguments createArguments() { return new K2JSCompilerArguments(); } diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt index 43ef01aa15f..c7762650b59 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt @@ -24,9 +24,9 @@ import org.jetbrains.kotlin.cli.common.CLICompiler import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments -import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments -import org.jetbrains.kotlin.cli.common.arguments.K2MetadataCompilerArguments +import org.jetbrains.kotlin.cli.common.arguments.parseCommandLineArguments +import org.jetbrains.kotlin.cli.common.arguments.validateArguments import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageRenderer @@ -53,7 +53,6 @@ import org.jetbrains.kotlin.incremental.* import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents import org.jetbrains.kotlin.modules.Module import org.jetbrains.kotlin.progress.CompilationCanceledStatus -import org.jetbrains.kotlin.utils.stackTraceStr import java.io.BufferedOutputStream import java.io.ByteArrayOutputStream import java.io.File @@ -336,33 +335,35 @@ class CompileServiceImpl( ): CompileService.CallResult = ifAlive { val messageCollector = CompileServicesFacadeMessageCollector(servicesFacade, compilationOptions) val daemonReporter = DaemonMessageReporter(servicesFacade, compilationOptions) - val compilerMode = compilationOptions.compilerMode val targetPlatform = compilationOptions.targetPlatform log.info("Starting compilation with args: " + compilerArguments.joinToString(" ")) - val k2PlatformArgs = try { - when (targetPlatform) { - CompileService.TargetPlatform.JVM -> K2JVMCompilerArguments().apply { K2JVMCompiler().parseArguments(compilerArguments, this) } - CompileService.TargetPlatform.JS -> K2JSCompilerArguments().apply { K2JSCompiler().parseArguments(compilerArguments, this) } - CompileService.TargetPlatform.METADATA -> K2MetadataCompilerArguments().apply { K2MetadataCompiler().parseArguments(compilerArguments, this) } - } - } - catch (e: IllegalArgumentException) { - messageCollector.report(CompilerMessageSeverity.EXCEPTION, e.stackTraceStr) - return@ifAlive CompileService.CallResult.Error("Could not deserialize compiler arguments") - } - return@ifAlive when (compilerMode) { + @Suppress("UNCHECKED_CAST") + val compiler = when (targetPlatform) { + CompileService.TargetPlatform.JVM -> K2JVMCompiler() + CompileService.TargetPlatform.JS -> K2JSCompiler() + CompileService.TargetPlatform.METADATA -> K2MetadataCompiler() + } as CLICompiler + + val k2PlatformArgs = compiler.createArguments() + parseCommandLineArguments(compilerArguments, k2PlatformArgs) + val argumentParseError = validateArguments(k2PlatformArgs.errors) + if (argumentParseError != null) { + messageCollector.report(CompilerMessageSeverity.ERROR, argumentParseError) + CompileService.CallResult.Good(ExitCode.COMPILATION_ERROR.code) + } + else when (compilationOptions.compilerMode) { CompilerMode.JPS_COMPILER -> { val jpsServicesFacade = servicesFacade as JpsCompilerServicesFacade doCompile(sessionId, daemonReporter, tracer = null) { eventManger, profiler -> val services = createCompileServices(jpsServicesFacade, eventManger, profiler) - execCompiler(compilationOptions.targetPlatform, services, k2PlatformArgs, messageCollector) + compiler.exec(messageCollector, services, k2PlatformArgs) } } CompilerMode.NON_INCREMENTAL_COMPILER -> { doCompile(sessionId, daemonReporter, tracer = null) { _, _ -> - execCompiler(targetPlatform, Services.EMPTY, k2PlatformArgs, messageCollector) + compiler.exec(messageCollector, Services.EMPTY, k2PlatformArgs) } } CompilerMode.INCREMENTAL_COMPILER -> { @@ -382,28 +383,10 @@ class CompileServiceImpl( } } - else -> throw IllegalStateException("Unknown compilation mode $compilerMode") + else -> throw IllegalStateException("Unknown compilation mode ${compilationOptions.compilerMode}") } } - private fun execCompiler( - targetPlatform: CompileService.TargetPlatform, - services: Services, - args: CommonCompilerArguments, - messageCollector: MessageCollector - ): ExitCode = - when(targetPlatform) { - CompileService.TargetPlatform.JVM -> { - K2JVMCompiler().exec(messageCollector, services, args as K2JVMCompilerArguments) - } - CompileService.TargetPlatform.JS -> { - K2JSCompiler().exec(messageCollector, services, args as K2JSCompilerArguments) - } - CompileService.TargetPlatform.METADATA -> { - K2MetadataCompiler().exec(messageCollector, services, args as K2MetadataCompilerArguments) - } - } - private fun execIncrementalCompiler( k2jvmArgs: K2JVMCompilerArguments, incrementalCompilationOptions: IncrementalCompilationOptions, diff --git a/compiler/util/src/org/jetbrains/kotlin/utils/jvmUtils.kt b/compiler/util/src/org/jetbrains/kotlin/utils/jvmUtils.kt deleted file mode 100644 index 6756f321502..00000000000 --- a/compiler/util/src/org/jetbrains/kotlin/utils/jvmUtils.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.utils - -import java.io.PrintWriter -import java.io.StringWriter - -val Exception.stackTraceStr: String - get() { - val sw = StringWriter() - PrintWriter(sw).use { printStackTrace(it) } - return sw.toString() - } \ No newline at end of file