diff --git a/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/DaemonParams.kt b/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/DaemonParams.kt index 815ea746007..eacf096d24b 100644 --- a/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/DaemonParams.kt +++ b/compiler/rmi/rmi-interface/src/org/jetbrains/kotlin/rmi/DaemonParams.kt @@ -37,46 +37,6 @@ public val COMPILE_DAEMON_MEMORY_THRESHOLD_INFINITE: Long = 0L val COMPILER_ID_DIGEST = "MD5" -//open class PropExtractor>(val dest: C, -// val prop: P, -// val name: String, -// val convert: ((v: V) -> String?) = { it.toString() }, -// val skipIf: ((v: V) -> Boolean) = { false }, -// val mergeWithDelimiter: String? = null) -//{ -// constructor(dest: C, prop: P, convert: ((v: V) -> String?) = { it.toString() }, skipIf: ((v: V) -> Boolean) = { false }) : this(dest, prop, prop.name, convert, skipIf) -// open fun extract(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = -// when { -// skipIf(prop.get(dest)) -> listOf() -// mergeWithDelimiter != null -> listOf(prefix + name + mergeWithDelimiter + convert(prop.get(dest))).filterNotNull() -// else -> listOf(prefix + name, convert(prop.get(dest))).filterNotNull() -// } -//} -// -//class BoolPropExtractor>(dest: C, prop: P, name: String? = null) -// : PropExtractor(dest, prop, name ?: prop.name, convert = { null }, skipIf = { !prop.get(dest) }) -// -//class RestPropExtractor>>(dest: C, prop: P) : PropExtractor, P>(dest, prop, convert = { null }) { -// override fun extract(prefix: String): List = prop.get(dest).map { prefix + it } -//} -// -// -//open class PropParser>(val dest: C, -// val prop: P, alternativeNames: List, -// val parse: (s: String) -> V, -// val allowMergedArg: Boolean = false) { -// val names = listOf(prop.name) + alternativeNames -// constructor(dest: C, prop: P, parse: (s: String) -> V, allowMergedArg: Boolean = false) : this(dest, prop, listOf(), parse, allowMergedArg) -// fun apply(s: String) = prop.set(dest, parse(s)) -//} -// -//class BoolPropParser>(dest: C, prop: P): PropParser(dest, prop, { true }) -// -//class RestPropParser>>(dest: C, prop: P): PropParser, P>(dest, prop, { arrayListOf() }) { -// fun add(s: String) { prop.get(dest).add(s) } -//} - -// -------------------------------------------------------- open class PropMapper>(val dest: C, val prop: P, @@ -89,10 +49,10 @@ open class PropMapper>(val dest: C, open fun toArgs(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List = when { skipIf(prop.get(dest)) -> listOf() - mergeDelimiter != null -> listOf(prefix + names.first() + mergeDelimiter + toString(prop.get(dest))).filterNotNull() + mergeDelimiter != null -> listOf( listOf(prefix + names.first(), toString(prop.get(dest))).filterNotNull().joinToString(mergeDelimiter)) else -> listOf(prefix + names.first(), toString(prop.get(dest))).filterNotNull() } - fun apply(s: String) = prop.set(dest, fromString(s)) + open fun apply(s: String) = prop.set(dest, fromString(s)) } class StringPropMapper>(dest: C, @@ -113,69 +73,65 @@ class RestPropMapper>>(dest : PropMapper, P>(dest = dest, prop = prop, toString = { null }, fromString = { arrayListOf() }) { override fun toArgs(prefix: String): List = prop.get(dest).map { prefix + it } + override fun apply(s: String) = add(s) fun add(s: String) { prop.get(dest).add(s) } } -// ------------------------------------------ + +inline fun Iterable.firstMapOrNull(mappingPredicate: (T) -> Pair): R? { + for (element in this) { + val (found, mapped) = mappingPredicate(element) + if (found) return mapped + } + return null +} + fun Iterable.filterExtractProps(propMappers: List>, prefix: String, restParser: RestPropMapper<*,*>? = null) : Iterable { - var currentPropMapper: PropMapper<*,*,*>? = null - var matchingOption = "" - val res = filter { param -> - if (currentPropMapper == null) { - val propMapper = propMappers.find { - it !is RestPropMapper<*,*> && - it.names.any { name -> - if (param.startsWith(prefix + name)) { - matchingOption = prefix + name - true + + val iter = iterator() + val rest = arrayListOf() + + while (iter.hasNext()) { + val param = iter.next() + val (propMapper, matchingOption) = propMappers.firstMapOrNull { + val name = if (it !is RestPropMapper<*,*>) it.names.firstOrNull { param.startsWith(prefix + it) } else null + Pair(name != null, Pair(it, name)) + } ?: Pair(null, null) + + when { + propMapper != null -> { + val optionLength = prefix.length() + matchingOption!!.length() + when { + propMapper is BoolPropMapper<*,*> -> { + if (param.length() > optionLength) + throw IllegalArgumentException("Invalid switch option '$param', expecting $prefix$matchingOption without arguments") + propMapper.apply("") } - else { - false - } - } - } - when { - propMapper != null -> { - val optionLength = matchingOption.length() - when { - propMapper is BoolPropMapper<*,*> -> { - if (param.length() > optionLength) - throw IllegalArgumentException("Invalid switch option '$param', expecting $matchingOption without arguments") - propMapper.apply("") + param.length() > optionLength -> + if (param[optionLength] != '=') { + if (propMapper.mergeDelimiter == null) + throw IllegalArgumentException("Invalid option syntax '$param', expecting $prefix$matchingOption[= ]") + propMapper.apply(param.substring(optionLength)) } - param.length() > optionLength -> - if (param[optionLength] != '=') { - if (propMapper.mergeDelimiter == null) - throw IllegalArgumentException("Invalid option syntax '$param', expecting $matchingOption[= ]") - propMapper.apply(param.substring(optionLength)) - } - else { - propMapper.apply(param.substring(optionLength + 1)) - } - else -> - currentPropMapper = propMapper + else { + propMapper.apply(param.substring(optionLength + 1)) + } + else -> { + if (!iter.hasNext()) throw IllegalArgumentException("Expecting argument for the option $prefix$matchingOption") + propMapper.apply(iter.next()) } - false } - restParser != null && param.startsWith(prefix) -> { - restParser.add(param.removePrefix(prefix)) - false - } - else -> true } - } - else { - currentPropMapper!!.apply(param) - currentPropMapper = null - false + restParser != null && param.startsWith(prefix) -> + restParser.add(param.removePrefix(prefix)) + else -> rest.add(param) } } - if (currentPropMapper != null) - throw IllegalArgumentException("Expecting argument for the option $matchingOption") - return res + return rest } + // TODO: find out how to create more generic variant using first constructor //fun C.propsToParams() { // val kc = C::class @@ -196,7 +152,7 @@ public data class DaemonJVMOptions( public var maxMemory: String = "", public var maxPermSize: String = "", public var reservedCodeCacheSize: String = "", - public var otherJvmParams: MutableCollection = arrayListOf() + public var jvmParams: MutableCollection = arrayListOf() ) : OptionsGroup { override val mappers: List> @@ -206,7 +162,7 @@ public data class DaemonJVMOptions( restMapper) val restMapper: RestPropMapper<*,*> - get() = RestPropMapper(this, ::otherJvmParams) + get() = RestPropMapper(this, ::jvmParams) } public data class DaemonOptions( @@ -292,7 +248,7 @@ public fun configureDaemonLaunchingOptions(opts: DaemonJVMOptions, inheritMemory ManagementFactory.getRuntimeMXBean().inputArguments.filterExtractProps(opts.mappers, "-") System.getProperty(COMPILE_DAEMON_JVM_OPTIONS_PROPERTY)?.let { - opts.otherJvmParams.addAll( it.trim('"', '\'').split(",").filterExtractProps(opts.mappers, "-", opts.restMapper)) + opts.jvmParams.addAll(it.trim('"', '\'').split(",").filterExtractProps(opts.mappers, "-", opts.restMapper)) } return opts } diff --git a/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompileServiceImpl.kt b/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompileServiceImpl.kt index f3ca7bd58a9..797a6e7cb5c 100644 --- a/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompileServiceImpl.kt +++ b/compiler/rmi/rmi-server/src/org/jetbrains/kotlin/rmi/service/CompileServiceImpl.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.service import org.jetbrains.kotlin.cli.common.CLICompiler +import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache @@ -182,7 +183,7 @@ class CompileServiceImpl>( when (outputFormat) { CompileService.OutputFormat.PLAIN -> compiler.exec(printStream, *args) CompileService.OutputFormat.XML -> compiler.execAndOutputXml(printStream, Services.EMPTY, *args) - }.code + } } override fun remoteIncrementalCompile(args: Array, caches: Map, outputStream: RemoteOutputStream, outputFormat: CompileService.OutputFormat): Int = @@ -190,13 +191,13 @@ class CompileServiceImpl>( when (outputFormat) { CompileService.OutputFormat.PLAIN -> throw NotImplementedError("Only XML output is supported in remote incremental compilation") CompileService.OutputFormat.XML -> compiler.execAndOutputXml(printStream, createCompileServices(caches), *args) - }.code + } } - fun doCompile(args: Array, errStream: RemoteOutputStream, body: (PrintStream) -> Int): Int = + fun doCompile(args: Array, errStream: RemoteOutputStream, body: (PrintStream) -> ExitCode): Int = ifAlive { checkedCompile(args) { - body( PrintStream( RemoteOutputStreamClient(errStream))) + body( PrintStream( RemoteOutputStreamClient(errStream))).code } } }