diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt index 29ba2707a8f..46caa0f3a24 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt @@ -108,7 +108,8 @@ class Kapt3IT : BaseGradleIT() { assertSuccessful() assertKaptSuccessful() assertContains("Options: {suffix=Customized, justColon=:, justEquals==, containsColon=a:b, " + - "containsEquals=a=b, startsWithColon=:a, startsWithEquals==a, endsWithColon=a:, endsWithEquals=a:}") + "containsEquals=a=b, startsWithColon=:a, startsWithEquals==a, endsWithColon=a:, " + + "endsWithEquals=a:, withSpace=a b c}") assertFileExists("build/generated/source/kapt/main/example/TestClassCustomized.java") assertFileExists("build/classes/main/example/TestClass.class") assertFileExists("build/classes/main/example/TestClassCustomized.class") diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/arguments/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/arguments/build.gradle index 0f561175231..a0b3a029c58 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/arguments/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/arguments/build.gradle @@ -31,5 +31,6 @@ kapt { arg("startsWithEquals", "=a") arg("endsWithColon", "a:") arg("endsWithEquals", "a:") + arg("withSpace", "a b c") // key doesn't support spaces } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt3KotlinGradleSubplugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt3KotlinGradleSubplugin.kt index 3ce2102b745..4d07b3935a5 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt3KotlinGradleSubplugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt3KotlinGradleSubplugin.kt @@ -29,8 +29,11 @@ import org.gradle.api.tasks.compile.JavaCompile import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper import org.jetbrains.kotlin.gradle.tasks.KotlinCompile -import org.jetbrains.kotlin.gradle.tasks.SyncOutputTask +import java.io.ByteArrayOutputStream import java.io.File +import java.io.ObjectOutputStream +import javax.xml.bind.DatatypeConverter +import javax.xml.bind.DatatypeConverter.printBase64Binary // apply plugin: 'kotlin-kapt' class Kapt3GradleSubplugin : Plugin { @@ -171,15 +174,27 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin { val apOptions = kaptExtension.getAdditionalArguments(project, variantData, androidPlugin) + androidOptions - for ((key, value) in apOptions) { - pluginOptions += SubpluginOption("apoption", "$key:$value") - } + SubpluginOption("apoptions", encodeAnnotationProcessingOptions(apOptions)) addMiscOptions(pluginOptions) return pluginOptions } + fun encodeAnnotationProcessingOptions(options: Map): String { + val os = ByteArrayOutputStream() + val oos = ObjectOutputStream(os) + + oos.writeInt(options.size) + for ((k, v) in options.entries) { + oos.writeUTF(k) + oos.writeUTF(v) + } + + oos.flush() + return printBase64Binary(os.toByteArray()) + } + private fun Kapt3SubpluginContext.addMiscOptions(pluginOptions: MutableList) { if (kaptExtension.generateStubs) { project.logger.warn("'kapt.generateStubs' is not used by the 'kotlin-kapt' plugin") diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt index 24165dc1dac..03100c14689 100644 --- a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt @@ -37,15 +37,16 @@ import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.container.ComponentProvider import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.descriptors.PackageFragmentProvider import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages import org.jetbrains.kotlin.kapt3.diagnostic.DefaultErrorMessagesKapt3 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 java.io.ByteArrayInputStream import java.io.File -import java.util.* +import java.io.ObjectInputStream +import javax.xml.bind.DatatypeConverter object Kapt3ConfigurationKeys { val SOURCE_OUTPUT_DIR: CompilerConfigurationKey = @@ -63,8 +64,8 @@ object Kapt3ConfigurationKeys { val ANNOTATION_PROCESSOR_CLASSPATH: CompilerConfigurationKey> = CompilerConfigurationKey.create>("annotation processor classpath") - val APT_OPTIONS: CompilerConfigurationKey> = - CompilerConfigurationKey.create>("annotation processing options") + val APT_OPTIONS: CompilerConfigurationKey = + CompilerConfigurationKey.create("annotation processing options") val VERBOSE_MODE: CompilerConfigurationKey = CompilerConfigurationKey.create("verbose mode") @@ -100,8 +101,8 @@ class Kapt3CommandLineProcessor : CommandLineProcessor { required = false, allowMultipleOccurrences = true) val APT_OPTIONS_OPTION: CliOption = - CliOption("apoption", ":", "Annotation processor option", - required = false, allowMultipleOccurrences = true) + CliOption("apoptions", "options map", "Encoded annotation processor options", + required = false, allowMultipleOccurrences = false) val VERBOSE_MODE_OPTION: CliOption = CliOption("verbose", "true | false", "Enable verbose output", required = false) @@ -126,7 +127,7 @@ class Kapt3CommandLineProcessor : CommandLineProcessor { override fun processOption(option: CliOption, value: String, configuration: CompilerConfiguration) { when (option) { ANNOTATION_PROCESSOR_CLASSPATH_OPTION -> configuration.appendList(ANNOTATION_PROCESSOR_CLASSPATH, value) - APT_OPTIONS_OPTION -> configuration.appendList(APT_OPTIONS, value) + APT_OPTIONS_OPTION -> configuration.put(Kapt3ConfigurationKeys.APT_OPTIONS, value) SOURCE_OUTPUT_DIR_OPTION -> configuration.put(Kapt3ConfigurationKeys.SOURCE_OUTPUT_DIR, value) CLASS_OUTPUT_DIR_OPTION -> configuration.put(Kapt3ConfigurationKeys.CLASS_OUTPUT_DIR, value) STUBS_OUTPUT_DIR_OPTION -> configuration.put(Kapt3ConfigurationKeys.STUBS_OUTPUT_DIR, value) @@ -141,6 +142,24 @@ class Kapt3CommandLineProcessor : CommandLineProcessor { } class Kapt3ComponentRegistrar : ComponentRegistrar { + fun decodeAnnotationProcessingOptions(options: String): Map { + val map = LinkedHashMap() + + val decodedBytes = DatatypeConverter.parseBase64Binary(options) + val bis = ByteArrayInputStream(decodedBytes) + val ois = ObjectInputStream(bis) + + val n = ois.readInt() + + repeat(n) { + val k = ois.readUTF() + val v = ois.readUTF() + map[k] = v + } + + return map + } + override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) { val isAptOnly = configuration.get(Kapt3ConfigurationKeys.APT_ONLY) == "true" val isVerbose = configuration.get(Kapt3ConfigurationKeys.VERBOSE_MODE) == "true" @@ -170,11 +189,7 @@ class Kapt3ComponentRegistrar : ComponentRegistrar { return } - val apOptions = (configuration.get(APT_OPTIONS) ?: listOf()) - .map { it.split(':', limit = 2) } - .filter { it.isNotEmpty() } - .map { it[0] to it.getOrElse(1) { "" } } - .toMap() + val apOptions = configuration.get(APT_OPTIONS)?.let { decodeAnnotationProcessingOptions(it) } ?: emptyMap() sourcesOutputDir.mkdirs()