Encode all compiler plugin arguments for Android Extensions in kapt
Commas in option values breaks the option parsing in daemon (KT-20235).
This commit is contained in:
@@ -30,4 +30,14 @@ interface CommandLineProcessor {
|
||||
paths.add(value)
|
||||
put(option, paths)
|
||||
}
|
||||
|
||||
fun CompilerConfiguration.applyOptionsFrom(map: Map<String, List<String>>, pluginOptions: Collection<CliOption>) {
|
||||
for ((key, values) in map) {
|
||||
val option = pluginOptions.firstOrNull { it.name == key } ?: continue
|
||||
|
||||
for (value in values) {
|
||||
processOption(option, value, this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
-d
|
||||
$TEMP_DIR$
|
||||
-Xplugin=dist/kotlinc/lib/android-extensions-compiler.jar
|
||||
-P
|
||||
plugin\:org.jetbrains.kotlin.android\:package=com.myapp
|
||||
$TESTDATA_DIR$/pluginSimple.kt
|
||||
$TESTDATA_DIR$/androidPlugin/androidApp.kt
|
||||
$TESTDATA_DIR$/androidPlugin/androidView.kt
|
||||
$TESTDATA_DIR$/androidPlugin/androidWidget.kt
|
||||
$TESTDATA_DIR$/androidPlugin/fakeAppwidgetPackage.kt
|
||||
$TESTDATA_DIR$/androidPlugin/fakeInputMethodServicePackage.kt
|
||||
$TESTDATA_DIR$/androidPlugin/fakeOpenglPackage.kt
|
||||
$TESTDATA_DIR$/androidPlugin/fakeWebkitPackage.kt
|
||||
@@ -1,8 +0,0 @@
|
||||
import android.view.*
|
||||
import android.app.*
|
||||
import android.widget.*
|
||||
import kotlinx.android.synthetic.main.layout.*
|
||||
|
||||
class MyActivity : Activity() {
|
||||
{ textView.setText("Some text") }
|
||||
}
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
error: required plugin option not present: org.jetbrains.kotlin.android:variant
|
||||
|
||||
Plugin "org.jetbrains.kotlin.android" usage:
|
||||
variant <name;path> Android build variant (required, multiple)
|
||||
package <fq name> Application package (required)
|
||||
experimental true/false Enable experimental features
|
||||
defaultCacheImplementation hashMap/sparseArray/none
|
||||
Default cache implementation for module
|
||||
|
||||
COMPILATION_ERROR
|
||||
@@ -398,12 +398,6 @@ public class CliTestGenerated extends AbstractCliTest {
|
||||
doJvmTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("pluginSimpleUsage.args")
|
||||
public void testPluginSimpleUsage() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/pluginSimpleUsage.args");
|
||||
doJvmTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("returnAsWhenKey.args")
|
||||
public void testReturnAsWhenKey() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/returnAsWhenKey.args");
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.ByteArrayInputStream
|
||||
import java.io.ObjectInputStream
|
||||
import java.util.*
|
||||
|
||||
fun decodePluginOptions(options: String): Map<String, List<String>> {
|
||||
val map = LinkedHashMap<String, List<String>>()
|
||||
|
||||
val decodedBytes = Base64.getDecoder().decode(options)
|
||||
val bis = ByteArrayInputStream(decodedBytes)
|
||||
val ois = ObjectInputStream(bis)
|
||||
|
||||
val n = ois.readInt()
|
||||
|
||||
repeat(n) {
|
||||
val key = ois.readUTF()
|
||||
|
||||
val valueCount = ois.readInt()
|
||||
val values = mutableListOf<String>()
|
||||
|
||||
repeat(valueCount) {
|
||||
values += ois.readUTF()
|
||||
}
|
||||
|
||||
map[key] = values
|
||||
}
|
||||
|
||||
return map
|
||||
}
|
||||
+2
-2
@@ -128,7 +128,7 @@ class AndroidSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
addVariant(sourceSet)
|
||||
}
|
||||
|
||||
return pluginOptions
|
||||
return wrapPluginOptions(pluginOptions, "configuration")
|
||||
}
|
||||
|
||||
private fun getLayoutDirectories(resDirectories: Collection<File>): List<File> {
|
||||
@@ -198,7 +198,7 @@ class AndroidSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
addSourceSetAsVariant(variantName)
|
||||
}
|
||||
|
||||
return pluginOptions
|
||||
return wrapPluginOptions(pluginOptions, "configuration")
|
||||
}
|
||||
|
||||
// Android25ProjectHandler.KaptVariant actually contains BaseVariant, not BaseVariantData
|
||||
|
||||
+9
-9
@@ -30,12 +30,12 @@ import org.gradle.api.tasks.compile.JavaCompile
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.File
|
||||
import java.io.ObjectOutputStream
|
||||
import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin.Companion.getKaptGeneratedSourcesDir
|
||||
import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin.Companion.getKaptGeneratedClassesDir
|
||||
import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin.Companion.getKaptGeneratedKotlinSourcesDir
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.ObjectOutputStream
|
||||
import java.util.*
|
||||
|
||||
// apply plugin: 'kotlin-kapt'
|
||||
@@ -234,9 +234,9 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
androidPlugin
|
||||
) + androidOptions + mapOf("kapt.kotlin.generated" to kotlinSourcesOutputDir.absolutePath)
|
||||
|
||||
pluginOptions += SubpluginOption("apoptions", encodeOptions(apOptions))
|
||||
pluginOptions += SubpluginOption("apoptions", encodeList(apOptions))
|
||||
|
||||
pluginOptions += SubpluginOption("javacArguments", encodeOptions(kaptExtension.getJavacOptions()))
|
||||
pluginOptions += SubpluginOption("javacArguments", encodeList(kaptExtension.getJavacOptions()))
|
||||
|
||||
addMiscOptions(pluginOptions)
|
||||
|
||||
@@ -245,19 +245,19 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
|
||||
private fun Kapt3SubpluginContext.buildAndAddOptionsTo(container: CompilerPluginOptions, aptMode: String) {
|
||||
val compilerPluginId = getCompilerPluginId()
|
||||
for (option in buildOptions(aptMode)) {
|
||||
for (option in wrapPluginOptions(buildOptions(aptMode), "configuration")) {
|
||||
container.addPluginArgument(compilerPluginId, option.key, option.value)
|
||||
}
|
||||
}
|
||||
|
||||
fun encodeOptions(options: Map<String, String>): String {
|
||||
private fun encodeList(options: Map<String, String>): String {
|
||||
val os = ByteArrayOutputStream()
|
||||
val oos = ObjectOutputStream(os)
|
||||
|
||||
oos.writeInt(options.size)
|
||||
for ((k, v) in options.entries) {
|
||||
oos.writeUTF(k)
|
||||
oos.writeUTF(v)
|
||||
for ((key, value) in options.entries) {
|
||||
oos.writeUTF(key)
|
||||
oos.writeUTF(value)
|
||||
}
|
||||
|
||||
oos.flush()
|
||||
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.gradle.internal
|
||||
|
||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginOption
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.ObjectOutputStream
|
||||
import java.util.*
|
||||
|
||||
fun encodePluginOptions(options: Map<String, List<String>>): String {
|
||||
val os = ByteArrayOutputStream()
|
||||
val oos = ObjectOutputStream(os)
|
||||
|
||||
oos.writeInt(options.size)
|
||||
for ((key, values) in options.entries) {
|
||||
oos.writeUTF(key)
|
||||
|
||||
oos.writeInt(values.size)
|
||||
for (value in values) {
|
||||
oos.writeUTF(value)
|
||||
}
|
||||
}
|
||||
|
||||
oos.flush()
|
||||
return Base64.getEncoder().encodeToString(os.toByteArray())
|
||||
}
|
||||
|
||||
fun wrapPluginOptions(options: List<SubpluginOption>, newOptionName: String): List<SubpluginOption> {
|
||||
val groupedOptions = options.groupBy { it.key }.mapValues { opt -> opt.value.map { it.value } }
|
||||
val encodedOptions = encodePluginOptions(groupedOptions)
|
||||
val singleOption = SubpluginOption(newOptionName, encodedOptions)
|
||||
return listOf(singleOption)
|
||||
}
|
||||
+9
-5
@@ -47,6 +47,7 @@ import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension
|
||||
import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
||||
import org.jetbrains.kotlin.utils.decodePluginOptions
|
||||
|
||||
object AndroidConfigurationKeys {
|
||||
val VARIANT = CompilerConfigurationKey.create<List<String>>("Android build variant")
|
||||
@@ -59,8 +60,10 @@ class AndroidCommandLineProcessor : CommandLineProcessor {
|
||||
companion object {
|
||||
val ANDROID_COMPILER_PLUGIN_ID: String = "org.jetbrains.kotlin.android"
|
||||
|
||||
val VARIANT_OPTION = CliOption("variant", "<name;path>", "Android build variant", allowMultipleOccurrences = true)
|
||||
val PACKAGE_OPTION = CliOption("package", "<fq name>", "Application package")
|
||||
val CONFIGURATION = CliOption("configuration", "<encoded>", "Encoded configuration", required = false)
|
||||
|
||||
val VARIANT_OPTION = CliOption("variant", "<name;path>", "Android build variant", allowMultipleOccurrences = true, required = false)
|
||||
val PACKAGE_OPTION = CliOption("package", "<fq name>", "Application package", required = false)
|
||||
val EXPERIMENTAL_OPTION = CliOption("experimental", "true/false", "Enable experimental features", required = false)
|
||||
val DEFAULT_CACHE_IMPL_OPTION = CliOption(
|
||||
"defaultCacheImplementation", "hashMap/sparseArray/none", "Default cache implementation for module", required = false)
|
||||
@@ -72,7 +75,7 @@ class AndroidCommandLineProcessor : CommandLineProcessor {
|
||||
override val pluginId: String = ANDROID_COMPILER_PLUGIN_ID
|
||||
|
||||
override val pluginOptions: Collection<CliOption>
|
||||
= listOf(VARIANT_OPTION, PACKAGE_OPTION, EXPERIMENTAL_OPTION, DEFAULT_CACHE_IMPL_OPTION)
|
||||
= listOf(VARIANT_OPTION, PACKAGE_OPTION, EXPERIMENTAL_OPTION, DEFAULT_CACHE_IMPL_OPTION, CONFIGURATION)
|
||||
|
||||
override fun processOption(option: CliOption, value: String, configuration: CompilerConfiguration) {
|
||||
when (option) {
|
||||
@@ -80,6 +83,7 @@ class AndroidCommandLineProcessor : CommandLineProcessor {
|
||||
PACKAGE_OPTION -> configuration.put(AndroidConfigurationKeys.PACKAGE, value)
|
||||
EXPERIMENTAL_OPTION -> configuration.put(AndroidConfigurationKeys.EXPERIMENTAL, value)
|
||||
DEFAULT_CACHE_IMPL_OPTION -> configuration.put(AndroidConfigurationKeys.DEFAULT_CACHE_IMPL, value)
|
||||
CONFIGURATION -> configuration.applyOptionsFrom(decodePluginOptions(value), pluginOptions)
|
||||
else -> throw CliOptionProcessingException("Unknown option: ${option.name}")
|
||||
}
|
||||
}
|
||||
@@ -101,8 +105,8 @@ class AndroidComponentRegistrar : ComponentRegistrar {
|
||||
}
|
||||
|
||||
override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
|
||||
val applicationPackage = configuration.get(AndroidConfigurationKeys.PACKAGE)
|
||||
val variants = configuration.get(AndroidConfigurationKeys.VARIANT)?.mapNotNull { parseVariant(it) } ?: emptyList()
|
||||
val applicationPackage = configuration.get(AndroidConfigurationKeys.PACKAGE) ?: return
|
||||
val variants = configuration.get(AndroidConfigurationKeys.VARIANT)?.mapNotNull { parseVariant(it) } ?: return
|
||||
val isExperimental = configuration.get(AndroidConfigurationKeys.EXPERIMENTAL) == "true"
|
||||
val globalCacheImpl = parseCacheImplementationType(configuration.get(AndroidConfigurationKeys.DEFAULT_CACHE_IMPL))
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.kapt3.util.KaptLogger
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension
|
||||
import org.jetbrains.kotlin.utils.decodePluginOptions
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.File
|
||||
import java.io.ObjectInputStream
|
||||
@@ -93,6 +94,8 @@ class Kapt3CommandLineProcessor : CommandLineProcessor {
|
||||
companion object {
|
||||
val ANNOTATION_PROCESSING_COMPILER_PLUGIN_ID: String = "org.jetbrains.kotlin.kapt3"
|
||||
|
||||
val CONFIGURATION = CliOption("configuration", "<encoded>", "Encoded configuration", required = false)
|
||||
|
||||
val SOURCE_OUTPUT_DIR_OPTION: CliOption =
|
||||
CliOption("sources", "<path>", "Output path for the generated files", required = false)
|
||||
|
||||
@@ -145,7 +148,8 @@ class Kapt3CommandLineProcessor : CommandLineProcessor {
|
||||
override val pluginOptions: Collection<CliOption> =
|
||||
listOf(SOURCE_OUTPUT_DIR_OPTION, ANNOTATION_PROCESSOR_CLASSPATH_OPTION, APT_OPTIONS_OPTION, JAVAC_CLI_OPTIONS_OPTION,
|
||||
CLASS_OUTPUT_DIR_OPTION, VERBOSE_MODE_OPTION, STUBS_OUTPUT_DIR_OPTION, APT_ONLY_OPTION, APT_MODE_OPTION,
|
||||
USE_LIGHT_ANALYSIS_OPTION, CORRECT_ERROR_TYPES_OPTION, ANNOTATION_PROCESSORS_OPTION, INCREMENTAL_DATA_OUTPUT_DIR_OPTION)
|
||||
USE_LIGHT_ANALYSIS_OPTION, CORRECT_ERROR_TYPES_OPTION, ANNOTATION_PROCESSORS_OPTION, INCREMENTAL_DATA_OUTPUT_DIR_OPTION,
|
||||
CONFIGURATION)
|
||||
|
||||
override fun processOption(option: CliOption, value: String, configuration: CompilerConfiguration) {
|
||||
when (option) {
|
||||
@@ -162,6 +166,7 @@ class Kapt3CommandLineProcessor : CommandLineProcessor {
|
||||
APT_MODE_OPTION -> configuration.put(Kapt3ConfigurationKeys.APT_MODE, value)
|
||||
USE_LIGHT_ANALYSIS_OPTION -> configuration.put(Kapt3ConfigurationKeys.USE_LIGHT_ANALYSIS, value)
|
||||
CORRECT_ERROR_TYPES_OPTION -> configuration.put(Kapt3ConfigurationKeys.CORRECT_ERROR_TYPES, value)
|
||||
CONFIGURATION -> configuration.applyOptionsFrom(decodePluginOptions(value), pluginOptions)
|
||||
else -> throw CliOptionProcessingException("Unknown option: ${option.name}")
|
||||
}
|
||||
}
|
||||
@@ -172,7 +177,7 @@ class Kapt3ComponentRegistrar : ComponentRegistrar {
|
||||
private const val JAVAC_CONTEXT_CLASS = "com.sun.tools.javac.util.Context"
|
||||
}
|
||||
|
||||
fun decodeOptions(options: String): Map<String, String> {
|
||||
private fun decodeList(options: String): Map<String, String> {
|
||||
val map = LinkedHashMap<String, String>()
|
||||
|
||||
val decodedBytes = Base64.getDecoder().decode(options)
|
||||
@@ -232,8 +237,8 @@ class Kapt3ComponentRegistrar : ComponentRegistrar {
|
||||
return
|
||||
}
|
||||
|
||||
val apOptions = configuration.get(APT_OPTIONS)?.let { decodeOptions(it) } ?: emptyMap()
|
||||
val javacCliOptions = configuration.get(JAVAC_CLI_OPTIONS)?.let { decodeOptions(it) } ?: emptyMap()
|
||||
val apOptions = configuration.get(APT_OPTIONS)?.let { decodeList(it) } ?: emptyMap()
|
||||
val javacCliOptions = configuration.get(JAVAC_CLI_OPTIONS)?.let { decodeList(it) } ?: emptyMap()
|
||||
|
||||
sourcesOutputDir.mkdirs()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user