Skip to content

Commit 3ee65ac

Browse files
committed
Kapt: Support specifying javac options (KT-17245)
1 parent 8cdb08c commit 3ee65ac

File tree

8 files changed

+82
-27
lines changed

8 files changed

+82
-27
lines changed

libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,8 @@ class Kapt3IT : BaseGradleIT() {
124124
assertKaptSuccessful()
125125
assertContains("Options: {suffix=Customized, justColon=:, justEquals==, containsColon=a:b, " +
126126
"containsEquals=a=b, startsWithColon=:a, startsWithEquals==a, endsWithColon=a:, " +
127-
"endsWithEquals=a:, withSpace=a b c}")
127+
"endsWithEquals=a:, withSpace=a b c,")
128+
assertContains("-Xmaxerrs=500, -Xlint:all=-Xlint:all") // Javac options test
128129
assertFileExists("build/generated/source/kapt/main/example/TestClassCustomized.java")
129130
assertFileExists("build/classes/main/example/TestClass.class")
130131
assertFileExists("build/classes/main/example/TestClassCustomized.class")

libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/arguments/build.gradle

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,9 @@ kapt {
3333
arg("endsWithEquals", "a:")
3434
arg("withSpace", "a b c") // key doesn't support spaces
3535
}
36+
37+
javacOptions {
38+
option("-Xmaxerrs", 500)
39+
option("-Xlint:all")
40+
}
3641
}

libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt3KotlinGradleSubplugin.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import org.gradle.api.tasks.compile.JavaCompile
2929
import org.jetbrains.kotlin.gradle.plugin.*
3030
import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper
3131
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
32-
import org.jetbrains.kotlin.preprocessor.mkdirsOrFail
3332
import java.io.ByteArrayOutputStream
3433
import java.io.File
3534
import java.io.ObjectOutputStream
@@ -193,14 +192,16 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
193192
androidOptions +
194193
mapOf("kapt.kotlin.generated" to kotlinSourcesOutputDir.absolutePath)
195194

196-
pluginOptions += SubpluginOption("apoptions", encodeAnnotationProcessingOptions(apOptions))
195+
pluginOptions += SubpluginOption("apoptions", encodeOptions(apOptions))
196+
197+
pluginOptions += SubpluginOption("javacArguments", encodeOptions(kaptExtension.getJavacOptions()))
197198

198199
addMiscOptions(pluginOptions)
199200

200201
return pluginOptions
201202
}
202203

203-
fun encodeAnnotationProcessingOptions(options: Map<String, String>): String {
204+
fun encodeOptions(options: Map<String, String>): String {
204205
val os = ByteArrayOutputStream()
205206
val oos = ObjectOutputStream(os)
206207

libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KaptExtension.kt

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,29 @@ open class KaptExtension {
3232

3333
open var processors: String = ""
3434

35-
private var closure: Closure<*>? = null
35+
private var apOptionsClosure: Closure<*>? = null
36+
private var javacOptionsClosure: Closure<*>? = null
3637

3738
open fun arguments(closure: Closure<*>) {
38-
this.closure = closure
39+
this.apOptionsClosure = closure
40+
}
41+
42+
open fun javacOptions(closure: Closure<*>) {
43+
this.javacOptionsClosure = closure
44+
}
45+
46+
fun getJavacOptions(): Map<String, String> {
47+
val closureToExecute = javacOptionsClosure ?: return emptyMap()
48+
val executor = KaptJavacOptionsDelegate().apply { execute(closureToExecute) }
49+
return executor.options
3950
}
4051

4152
fun getAdditionalArguments(project: Project, variantData: Any?, androidExtension: Any?): Map<String, String> {
42-
val closureToExecute = closure ?: return emptyMap()
53+
val closureToExecute = apOptionsClosure ?: return emptyMap()
4354

44-
val executor = KaptAdditionalArgumentsDelegate(project, variantData, androidExtension)
55+
val executor = KaptAnnotationProcessorOptions(project, variantData, androidExtension)
4556
executor.execute(closureToExecute)
46-
return executor.args
57+
return executor.options
4758
}
4859

4960
fun getAdditionalArgumentsForJavac(project: Project, variantData: Any?, androidExtension: Any?): List<String> {
@@ -58,16 +69,16 @@ open class KaptExtension {
5869
/**
5970
* [project], [variant] and [android] properties are intended to be used inside the closure.
6071
*/
61-
open class KaptAdditionalArgumentsDelegate(
72+
open class KaptAnnotationProcessorOptions(
6273
@Suppress("unused") open val project: Project,
6374
@Suppress("unused") open val variant: Any?,
6475
@Suppress("unused") open val android: Any?
6576
) {
66-
internal val args = LinkedHashMap<String, String>()
77+
internal val options = LinkedHashMap<String, String>()
6778

6879
@Suppress("unused")
6980
open fun arg(name: Any, vararg values: Any) {
70-
args.put(name.toString(), values.joinToString(" "))
81+
options.put(name.toString(), values.joinToString(" "))
7182
}
7283

7384
fun execute(closure: Closure<*>) {
@@ -76,4 +87,22 @@ open class KaptAdditionalArgumentsDelegate(
7687
closure.call()
7788
}
7889

90+
}
91+
92+
open class KaptJavacOptionsDelegate {
93+
internal val options = LinkedHashMap<String, String>()
94+
95+
open fun option(name: Any, value: Any) {
96+
options.put(name.toString(), value.toString())
97+
}
98+
99+
open fun option(name: Any) {
100+
options.put(name.toString(), "")
101+
}
102+
103+
fun execute(closure: Closure<*>) {
104+
closure.resolveStrategy = Closure.DELEGATE_FIRST
105+
closure.delegate = this
106+
closure.call()
107+
}
79108
}

plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3Extension.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,15 @@ class ClasspathBasedKapt3Extension(
5151
stubsOutputDir: File,
5252
incrementalDataOutputDir: File?,
5353
options: Map<String, String>,
54+
javacOptions: Map<String, String>,
5455
annotationProcessors: String,
5556
aptOnly: Boolean,
5657
val useLightAnalysis: Boolean,
5758
correctErrorTypes: Boolean,
5859
pluginInitializedTime: Long,
5960
logger: KaptLogger
6061
) : AbstractKapt3Extension(compileClasspath, annotationProcessingClasspath, javaSourceRoots, sourcesOutputDir,
61-
classFilesOutputDir, stubsOutputDir, incrementalDataOutputDir, options, annotationProcessors,
62+
classFilesOutputDir, stubsOutputDir, incrementalDataOutputDir, options, javacOptions, annotationProcessors,
6263
aptOnly, pluginInitializedTime, logger, correctErrorTypes) {
6364
override val analyzePartially: Boolean
6465
get() = useLightAnalysis
@@ -103,6 +104,7 @@ abstract class AbstractKapt3Extension(
103104
val stubsOutputDir: File,
104105
val incrementalDataOutputDir: File?,
105106
val options: Map<String, String>,
107+
val javacOptions: Map<String, String>,
106108
val annotationProcessors: String,
107109
val aptOnly: Boolean,
108110
val pluginInitializedTime: Long,
@@ -204,7 +206,7 @@ abstract class AbstractKapt3Extension(
204206
logger.info { "Stubs compilation took $classFilesCompilationTime ms" }
205207
logger.info { "Compiled classes: " + compiledClasses.joinToString { it.name } }
206208

207-
return Pair(KaptContext(logger, bindingContext, compiledClasses, origins, options), generationState)
209+
return Pair(KaptContext(logger, bindingContext, compiledClasses, origins, options, javacOptions), generationState)
208210
}
209211

210212
private fun generateKotlinSourceStubs(kaptContext: KaptContext, generationState: GenerationState) {

plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.container.ComponentProvider
3838
import org.jetbrains.kotlin.context.ProjectContext
3939
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
4040
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
41+
import org.jetbrains.kotlin.kapt3.Kapt3ConfigurationKeys.JAVAC_CLI_OPTIONS
4142
import org.jetbrains.kotlin.kapt3.diagnostic.DefaultErrorMessagesKapt3
4243
import org.jetbrains.kotlin.kapt3.util.KaptLogger
4344
import org.jetbrains.kotlin.psi.KtFile
@@ -67,6 +68,9 @@ object Kapt3ConfigurationKeys {
6768
val APT_OPTIONS: CompilerConfigurationKey<String> =
6869
CompilerConfigurationKey.create<String>("annotation processing options")
6970

71+
val JAVAC_CLI_OPTIONS: CompilerConfigurationKey<String> =
72+
CompilerConfigurationKey.create<String>("javac CLI options")
73+
7074
val ANNOTATION_PROCESSORS: CompilerConfigurationKey<String> =
7175
CompilerConfigurationKey.create<String>("annotation processor qualified names")
7276

@@ -107,6 +111,10 @@ class Kapt3CommandLineProcessor : CommandLineProcessor {
107111
CliOption("apoptions", "options map", "Encoded annotation processor options",
108112
required = false, allowMultipleOccurrences = false)
109113

114+
val JAVAC_CLI_OPTIONS_OPTION: CliOption =
115+
CliOption("javacArguments", "javac CLI options map", "Encoded javac CLI options",
116+
required = false, allowMultipleOccurrences = false)
117+
110118
val ANNOTATION_PROCESSORS_OPTION: CliOption =
111119
CliOption("processors", "<fqname,[fqname2,...]>", "Annotation processor qualified names",
112120
required = false, allowMultipleOccurrences = true)
@@ -127,7 +135,7 @@ class Kapt3CommandLineProcessor : CommandLineProcessor {
127135
override val pluginId: String = ANNOTATION_PROCESSING_COMPILER_PLUGIN_ID
128136

129137
override val pluginOptions: Collection<CliOption> =
130-
listOf(SOURCE_OUTPUT_DIR_OPTION, ANNOTATION_PROCESSOR_CLASSPATH_OPTION, APT_OPTIONS_OPTION,
138+
listOf(SOURCE_OUTPUT_DIR_OPTION, ANNOTATION_PROCESSOR_CLASSPATH_OPTION, APT_OPTIONS_OPTION, JAVAC_CLI_OPTIONS_OPTION,
131139
CLASS_OUTPUT_DIR_OPTION, VERBOSE_MODE_OPTION, STUBS_OUTPUT_DIR_OPTION, APT_ONLY_OPTION,
132140
USE_LIGHT_ANALYSIS_OPTION, CORRECT_ERROR_TYPES_OPTION, ANNOTATION_PROCESSORS_OPTION)
133141

@@ -136,6 +144,7 @@ class Kapt3CommandLineProcessor : CommandLineProcessor {
136144
ANNOTATION_PROCESSOR_CLASSPATH_OPTION -> configuration.appendList(ANNOTATION_PROCESSOR_CLASSPATH, value)
137145
ANNOTATION_PROCESSORS_OPTION -> configuration.put(Kapt3ConfigurationKeys.ANNOTATION_PROCESSORS, value)
138146
APT_OPTIONS_OPTION -> configuration.put(Kapt3ConfigurationKeys.APT_OPTIONS, value)
147+
JAVAC_CLI_OPTIONS_OPTION -> configuration.put(Kapt3ConfigurationKeys.JAVAC_CLI_OPTIONS, value)
139148
SOURCE_OUTPUT_DIR_OPTION -> configuration.put(Kapt3ConfigurationKeys.SOURCE_OUTPUT_DIR, value)
140149
CLASS_OUTPUT_DIR_OPTION -> configuration.put(Kapt3ConfigurationKeys.CLASS_OUTPUT_DIR, value)
141150
STUBS_OUTPUT_DIR_OPTION -> configuration.put(Kapt3ConfigurationKeys.STUBS_OUTPUT_DIR, value)
@@ -150,7 +159,7 @@ class Kapt3CommandLineProcessor : CommandLineProcessor {
150159
}
151160

152161
class Kapt3ComponentRegistrar : ComponentRegistrar {
153-
fun decodeAnnotationProcessingOptions(options: String): Map<String, String> {
162+
fun decodeOptions(options: String): Map<String, String> {
154163
val map = LinkedHashMap<String, String>()
155164

156165
val decodedBytes = DatatypeConverter.parseBase64Binary(options)
@@ -199,7 +208,8 @@ class Kapt3ComponentRegistrar : ComponentRegistrar {
199208
return
200209
}
201210

202-
val apOptions = configuration.get(APT_OPTIONS)?.let { decodeAnnotationProcessingOptions(it) } ?: emptyMap()
211+
val apOptions = configuration.get(APT_OPTIONS)?.let { decodeOptions(it) } ?: emptyMap()
212+
val javacCliOptions = configuration.get(JAVAC_CLI_OPTIONS)?.let { decodeOptions(it) } ?: emptyMap()
203213

204214
sourcesOutputDir.mkdirs()
205215

@@ -232,7 +242,7 @@ class Kapt3ComponentRegistrar : ComponentRegistrar {
232242

233243
val kapt3AnalysisCompletedHandlerExtension = ClasspathBasedKapt3Extension(
234244
compileClasspath, apClasspath, javaSourceRoots, sourcesOutputDir, classFilesOutputDir,
235-
stubsOutputDir, incrementalDataOutputDir, apOptions, annotationProcessors,
245+
stubsOutputDir, incrementalDataOutputDir, apOptions, javacCliOptions, annotationProcessors,
236246
isAptOnly, useLightAnalysis, correctErrorTypes, System.currentTimeMillis(), logger)
237247
AnalysisHandlerExtension.registerExtension(project, kapt3AnalysisCompletedHandlerExtension)
238248
}

plugins/kapt3/src/org/jetbrains/kotlin/kapt3/KaptContext.kt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.kapt3.javac.KaptTreeMaker
2727
import org.jetbrains.kotlin.kapt3.util.KaptLogger
2828
import org.jetbrains.kotlin.resolve.BindingContext
2929
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
30+
import org.jetbrains.kotlin.utils.keysToMap
3031
import org.jetbrains.org.objectweb.asm.tree.ClassNode
3132
import javax.tools.JavaFileManager
3233

@@ -35,7 +36,8 @@ class KaptContext(
3536
val bindingContext: BindingContext,
3637
val compiledClasses: List<ClassNode>,
3738
val origins: Map<Any, JvmDeclarationOrigin>,
38-
processorOptions: Map<String, String>
39+
processorOptions: Map<String, String>,
40+
javacOptions: Map<String, String> = emptyMap()
3941
) : AutoCloseable {
4042
val context = Context()
4143
val compiler: KaptJavaCompiler
@@ -61,6 +63,18 @@ class KaptContext(
6163
val option = if (value.isEmpty()) "-A$key" else "-A$key=$value"
6264
options.put(option, option) // key == value: it's intentional
6365
}
66+
67+
for ((key, value) in javacOptions) {
68+
if (value.isNotEmpty()) {
69+
options.put(key, value)
70+
} else {
71+
options.put(key, key)
72+
}
73+
}
74+
75+
if (logger.isVerbose) {
76+
logger.info("Javac options: " + options.keySet().keysToMap { key -> options[key] ?: "" })
77+
}
6478
}
6579

6680
override fun close() {

plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/AbstractKotlinKapt3IntegrationTest.kt

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ import com.sun.tools.javac.util.List as JavacList
5353
abstract class AbstractKotlinKapt3IntegrationTest : CodegenTestCase() {
5454
private companion object {
5555
val TEST_DATA_DIR = File("plugins/kapt3/testData/kotlinRunner")
56-
val messageCollector = PrintingMessageCollector(System.err, MessageRenderer.PLAIN_FULL_PATHS, false)
5756
}
5857

5958
private lateinit var processors: List<Processor>
@@ -66,12 +65,6 @@ abstract class AbstractKotlinKapt3IntegrationTest : CodegenTestCase() {
6665
process: (Set<TypeElement>, RoundEnvironment, ProcessingEnvironment) -> Unit
6766
) = testAP(true, name, options, process, *supportedAnnotations)
6867

69-
protected fun testShouldNotRun(
70-
name: String,
71-
vararg supportedAnnotations: String,
72-
options: Map<String, String> = emptyMap()
73-
) = testAP(false, name, options, { _, _, _ -> fail("Should not run") }, *supportedAnnotations)
74-
7568
protected fun testAP(
7669
shouldRun: Boolean,
7770
name: String,
@@ -162,7 +155,7 @@ abstract class AbstractKotlinKapt3IntegrationTest : CodegenTestCase() {
162155
incrementalDataOutputDir: File
163156
) : AbstractKapt3Extension(PathUtil.getJdkClassesRoots() + PathUtil.getKotlinPathsForIdeaPlugin().stdlibPath,
164157
emptyList(), javaSourceRoots, outputDir, outputDir,
165-
stubsOutputDir, incrementalDataOutputDir, options, "", true, System.currentTimeMillis(),
158+
stubsOutputDir, incrementalDataOutputDir, options, emptyMap(), "", true, System.currentTimeMillis(),
166159
KaptLogger(true), correctErrorTypes = true
167160
) {
168161
internal var savedStubs: String? = null

0 commit comments

Comments
 (0)