Next round of refactoring after review

This commit is contained in:
Ilya Chernikov
2015-08-31 19:10:28 +02:00
parent 9bee97e810
commit 7c1c628823
2 changed files with 55 additions and 98 deletions
@@ -37,46 +37,6 @@ public val COMPILE_DAEMON_MEMORY_THRESHOLD_INFINITE: Long = 0L
val COMPILER_ID_DIGEST = "MD5"
//open class PropExtractor<C, V, P: KProperty1<C, V>>(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<String> =
// when {
// skipIf(prop.get(dest)) -> listOf<String>()
// mergeWithDelimiter != null -> listOf(prefix + name + mergeWithDelimiter + convert(prop.get(dest))).filterNotNull()
// else -> listOf(prefix + name, convert(prop.get(dest))).filterNotNull()
// }
//}
//
//class BoolPropExtractor<C, P: KMutableProperty1<C, Boolean>>(dest: C, prop: P, name: String? = null)
// : PropExtractor<C, Boolean, P>(dest, prop, name ?: prop.name, convert = { null }, skipIf = { !prop.get(dest) })
//
//class RestPropExtractor<C, P: KMutableProperty1<C, out MutableCollection<String>>>(dest: C, prop: P) : PropExtractor<C, MutableCollection<String>, P>(dest, prop, convert = { null }) {
// override fun extract(prefix: String): List<String> = prop.get(dest).map { prefix + it }
//}
//
//
//open class PropParser<C, V, P: KMutableProperty1<C, V>>(val dest: C,
// val prop: P, alternativeNames: List<String>,
// 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<C, P: KMutableProperty1<C, Boolean>>(dest: C, prop: P): PropParser<C, Boolean, P>(dest, prop, { true })
//
//class RestPropParser<C, P: KMutableProperty1<C, MutableCollection<String>>>(dest: C, prop: P): PropParser<C, MutableCollection<String>, P>(dest, prop, { arrayListOf() }) {
// fun add(s: String) { prop.get(dest).add(s) }
//}
// --------------------------------------------------------
open class PropMapper<C, V, P: KMutableProperty1<C, V>>(val dest: C,
val prop: P,
@@ -89,10 +49,10 @@ open class PropMapper<C, V, P: KMutableProperty1<C, V>>(val dest: C,
open fun toArgs(prefix: String = COMPILE_DAEMON_CMDLINE_OPTIONS_PREFIX): List<String> =
when {
skipIf(prop.get(dest)) -> listOf<String>()
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<C, P: KMutableProperty1<C, String>>(dest: C,
@@ -113,69 +73,65 @@ class RestPropMapper<C, P: KMutableProperty1<C, MutableCollection<String>>>(dest
: PropMapper<C, MutableCollection<String>, P>(dest = dest, prop = prop, toString = { null }, fromString = { arrayListOf() })
{
override fun toArgs(prefix: String): List<String> = prop.get(dest).map { prefix + it }
override fun apply(s: String) = add(s)
fun add(s: String) { prop.get(dest).add(s) }
}
// ------------------------------------------
inline fun <T, R: Any> Iterable<T>.firstMapOrNull(mappingPredicate: (T) -> Pair<Boolean, R?>): R? {
for (element in this) {
val (found, mapped) = mappingPredicate(element)
if (found) return mapped
}
return null
}
fun Iterable<String>.filterExtractProps(propMappers: List<PropMapper<*,*,*>>, prefix: String, restParser: RestPropMapper<*,*>? = null) : Iterable<String> {
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<String>()
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[= ]<arg>")
propMapper.apply(param.substring(optionLength))
}
param.length() > optionLength ->
if (param[optionLength] != '=') {
if (propMapper.mergeDelimiter == null)
throw IllegalArgumentException("Invalid option syntax '$param', expecting $matchingOption[= ]<arg>")
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> 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<String> = arrayListOf()
public var jvmParams: MutableCollection<String> = arrayListOf()
) : OptionsGroup {
override val mappers: List<PropMapper<*,*,*>>
@@ -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
}
@@ -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<Compiler: CLICompiler<*>>(
when (outputFormat) {
CompileService.OutputFormat.PLAIN -> compiler.exec(printStream, *args)
CompileService.OutputFormat.XML -> compiler.execAndOutputXml(printStream, Services.EMPTY, *args)
}.code
}
}
override fun remoteIncrementalCompile(args: Array<out String>, caches: Map<String, CompileService.RemoteIncrementalCache>, outputStream: RemoteOutputStream, outputFormat: CompileService.OutputFormat): Int =
@@ -190,13 +191,13 @@ class CompileServiceImpl<Compiler: CLICompiler<*>>(
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<out String>, errStream: RemoteOutputStream, body: (PrintStream) -> Int): Int =
fun doCompile(args: Array<out String>, errStream: RemoteOutputStream, body: (PrintStream) -> ExitCode): Int =
ifAlive {
checkedCompile(args) {
body( PrintStream( RemoteOutputStreamClient(errStream)))
body( PrintStream( RemoteOutputStreamClient(errStream))).code
}
}
}