Kapt: Remove kapt1 support from Gradle and incremental compilation

This commit is contained in:
Yan Zhulanow
2018-05-16 23:45:24 +03:00
parent 58643ea99d
commit 662b79780d
15 changed files with 72 additions and 843 deletions
@@ -16,16 +16,4 @@
package org.jetbrains.kotlin.daemon.common
import java.rmi.RemoteException
interface IncrementalCompilerServicesFacade : CompilerServicesFacadeBase {
// AnnotationFileUpdater
@Throws(RemoteException::class)
fun hasAnnotationsFileUpdater(): Boolean
@Throws(RemoteException::class)
fun updateAnnotations(outdatedClassesJvmNames: Iterable<String>)
@Throws(RemoteException::class)
fun revert()
}
interface IncrementalCompilerServicesFacade : CompilerServicesFacadeBase
@@ -40,7 +40,6 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.metadata.K2MetadataCompiler
import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.daemon.common.*
import org.jetbrains.kotlin.daemon.incremental.RemoteAnnotationsFileUpdater
import org.jetbrains.kotlin.daemon.report.CompileServicesFacadeMessageCollector
import org.jetbrains.kotlin.daemon.report.DaemonMessageReporter
import org.jetbrains.kotlin.daemon.report.DaemonMessageReporterPrintStreamAdapter
@@ -486,7 +485,6 @@ class CompileServiceImpl(
daemonMessageReporter: DaemonMessageReporter
): ExitCode {
val reporter = RemoteICReporter(servicesFacade, compilationResults, incrementalCompilationOptions)
val annotationFileUpdater = if (servicesFacade.hasAnnotationsFileUpdater()) RemoteAnnotationsFileUpdater(servicesFacade) else null
val moduleFile = k2jvmArgs.buildFile?.let(::File)
assert(moduleFile?.exists() ?: false) { "Module does not exist ${k2jvmArgs.buildFile}" }
@@ -536,7 +534,7 @@ class CompileServiceImpl(
workingDir,
javaSourceRoots,
versions,
reporter, annotationFileUpdater,
reporter,
buildHistoryFile = incrementalCompilationOptions.multiModuleICSettings.buildHistoryFile,
localStateDirs = incrementalCompilationOptions.localStateDirs,
usePreciseJavaTracking = incrementalCompilationOptions.usePreciseJavaTracking,
@@ -1,35 +0,0 @@
/*
* Copyright 2010-2016 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.daemon.incremental
import org.jetbrains.kotlin.annotation.AnnotationFileUpdater
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.daemon.common.IncrementalCompilerServicesFacade
import org.jetbrains.kotlin.daemon.common.IncrementalCompilationServicesFacade
import org.jetbrains.kotlin.incremental.ICReporter
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import java.io.File
internal class RemoteAnnotationsFileUpdater(private val servicesFacade: IncrementalCompilerServicesFacade) : AnnotationFileUpdater {
override fun updateAnnotations(outdatedClasses: Iterable<JvmClassName>) {
servicesFacade.updateAnnotations(outdatedClasses.map { it.internalName })
}
override fun revert() {
servicesFacade.revert()
}
}
@@ -1,37 +0,0 @@
/*
* Copyright 2010-2016 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.annotation
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
/**
* Annotation file is generated by collecting annotated elements of generated files.
* When compiling incrementally, the compiler generates only subset of all classes,
* so after compilation annotation file contains only a subset of annotated elements,
* which breaks the build.
*
* The workaround is to:
* 1. backup old file before incremental compilation;
* 2. after each iteration of IC:
* 2.1 remove classes corresponding to dirty source files
* 2.2 add annotations from newly generated annotations file
*/
interface AnnotationFileUpdater {
fun updateAnnotations(outdatedClasses: Iterable<JvmClassName>)
fun revert()
}
@@ -22,7 +22,6 @@ import com.intellij.psi.PsiClass
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiFileFactory
import com.intellij.psi.PsiJavaFile
import org.jetbrains.kotlin.annotation.AnnotationFileUpdater
import org.jetbrains.kotlin.build.GeneratedFile
import org.jetbrains.kotlin.build.GeneratedJvmClass
import org.jetbrains.kotlin.build.JvmSourceRoot
@@ -103,7 +102,6 @@ class IncrementalJvmCompilerRunner(
private val javaSourceRoots: Set<JvmSourceRoot>,
cacheVersions: List<CacheVersion>,
reporter: ICReporter,
private var kaptAnnotationsFileUpdater: AnnotationFileUpdater? = null,
private val usePreciseJavaTracking: Boolean,
private val buildHistoryFile: File,
localStateDirs: Collection<File>,
@@ -311,28 +309,14 @@ class IncrementalJvmCompilerRunner(
}
override fun preBuildHook(args: K2JVMCompilerArguments, compilationMode: CompilationMode) {
when (compilationMode) {
is CompilationMode.Incremental -> {
val destinationDir = args.destinationAsFile
destinationDir.mkdirs()
args.classpathAsList = listOf(destinationDir) + args.classpathAsList
}
is CompilationMode.Rebuild -> {
// there is no point in updating annotation file since all files will be compiled anyway
kaptAnnotationsFileUpdater = null
}
if (compilationMode is CompilationMode.Incremental) {
val destinationDir = args.destinationAsFile
destinationDir.mkdirs()
args.classpathAsList = listOf(destinationDir) + args.classpathAsList
}
}
override fun postCompilationHook(exitCode: ExitCode) {
if (exitCode == ExitCode.OK) {
// TODO: Is it ok that argument always was an empty list?
kaptAnnotationsFileUpdater?.updateAnnotations(emptyList())
}
else {
kaptAnnotationsFileUpdater?.revert()
}
}
override fun postCompilationHook(exitCode: ExitCode) {}
override fun updateCaches(
services: Services,
@@ -41,13 +41,10 @@ class Android25ProjectHandler(kotlinConfigurationTools: KotlinConfigurationTools
androidExt: BaseExtension,
variantData: BaseVariant,
javaTask: AbstractCompile,
kotlinTask: KotlinCompile,
kotlinAfterJavaTask: KotlinCompile?) {
kotlinTask: KotlinCompile) {
val preJavaKotlinOutputFiles = mutableListOf<File>().apply {
if (kotlinAfterJavaTask == null) {
add(kotlinTask.destinationDir)
}
add(kotlinTask.destinationDir)
if (Kapt3GradleSubplugin.isEnabled(project)) {
// Add Kapt3 output as well, since there's no SyncOutputTask with the new API
val kaptClasssesDir = Kapt3GradleSubplugin.getKaptGeneratedClassesDir(project, getVariantName(variantData))
@@ -64,18 +61,6 @@ class Android25ProjectHandler(kotlinConfigurationTools: KotlinConfigurationTools
kotlinClasspath + project.files(AndroidGradleWrapper.getRuntimeJars(androidPlugin, androidExt))
}
// Use kapt1 annotations file for up-to-date check since annotation processing is done with javac
kotlinTask.kaptOptions.annotationsFile?.let { javaTask.inputs.file(it) }
if (kotlinAfterJavaTask != null) {
val kotlinAfterJavaOutput = project.files(kotlinAfterJavaTask.destinationDir).builtBy(kotlinAfterJavaTask)
variantData.registerPostJavacGeneratedBytecode(kotlinAfterJavaOutput)
// Then we don't need the kotlinTask output in artifacts, but we need to use it for Java compilation.
// Add it to Java classpath -- note the `from` used to avoid accident classpath resolution.
javaTask.classpath = project.files(kotlinTask.destinationDir).from(javaTask.classpath)
}
// Find the classpath entries that comes from the tested variant and register it as the friend path, lazily
kotlinTask.friendPaths = lazy {
variantData.getCompileClasspathArtifacts(preJavaClasspathKey)
@@ -1,46 +0,0 @@
package org.jetbrains.kotlin.annotation
import org.gradle.api.logging.Logging
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import java.io.File
internal class AnnotationFileUpdaterImpl(private val generatedAnnotationFile: File) : AnnotationFileUpdater {
private val logger = Logging.getLogger(this.javaClass)
private val lastSuccessfullyUpdatedFile = File.createTempFile("kapt-annotations-copy", "tmp")
init {
if (generatedAnnotationFile.exists()) {
generatedAnnotationFile.copyTo(lastSuccessfullyUpdatedFile, overwrite = true)
}
else {
lastSuccessfullyUpdatedFile.writeText("")
}
}
override fun updateAnnotations(outdatedClasses: Iterable<JvmClassName>) {
val outdatedClassesFqNames = outdatedClasses.mapTo(java.util.HashSet<String>()) { it.fqNameForClassNameWithoutDollars.asString() }
val annotationsProvider = MutableKotlinAnnotationProvider().apply {
addAnnotationsFrom(lastSuccessfullyUpdatedFile)
removeClasses(outdatedClassesFqNames)
logger.kotlinDebug { "Removed annotation entries for fq-names [${outdatedClassesFqNames.joinToString()}]" }
if (generatedAnnotationFile.exists()) {
addAnnotationsFrom(generatedAnnotationFile)
logger.kotlinDebug { "Added annotation entries from $generatedAnnotationFile" }
}
}
generatedAnnotationFile.delete()
generatedAnnotationFile.bufferedWriter().use { writer ->
annotationsProvider.writeAnnotations(CompactAnnotationWriter(writer))
logger.kotlinDebug { "Written updated annotations to $generatedAnnotationFile" }
}
generatedAnnotationFile.copyTo(lastSuccessfullyUpdatedFile, overwrite = true)
}
override fun revert() {
lastSuccessfullyUpdatedFile.copyTo(generatedAnnotationFile, overwrite = true)
}
}
@@ -1,6 +1,10 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.compilerRunner
import org.jetbrains.kotlin.annotation.AnnotationFileUpdater
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.daemon.common.MultiModuleICSettings
@@ -32,7 +36,6 @@ internal class GradleIncrementalCompilerEnvironment(
messageCollector: GradleMessageCollector,
outputItemsCollector: OutputItemsCollector,
compilerArgs: CommonCompilerArguments,
val kaptAnnotationsFileUpdater: AnnotationFileUpdater? = null,
val usePreciseJavaTracking: Boolean = false,
val localStateDirs: List<File> = emptyList(),
val multiModuleICSettings: MultiModuleICSettings
@@ -1,14 +1,16 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.compilerRunner
import org.gradle.api.Project
import org.gradle.api.logging.Logger
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.daemon.client.reportFromDaemon
import org.jetbrains.kotlin.daemon.common.*
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import java.io.Serializable
import java.rmi.Remote
import java.rmi.server.UnicastRemoteObject
@@ -45,20 +47,7 @@ internal open class GradleCompilerServicesFacadeImpl(
internal class GradleIncrementalCompilerServicesFacadeImpl(
project: Project,
private val environment: GradleIncrementalCompilerEnvironment,
environment: GradleIncrementalCompilerEnvironment,
port: Int = SOCKET_ANY_FREE_PORT
) : GradleCompilerServicesFacadeImpl(project, environment.messageCollector, port),
IncrementalCompilerServicesFacade {
override fun hasAnnotationsFileUpdater(): Boolean =
environment.kaptAnnotationsFileUpdater != null
override fun updateAnnotations(outdatedClassesJvmNames: Iterable<String>) {
val jvmNames = outdatedClassesJvmNames.map { JvmClassName.byInternalName(it) }
environment.kaptAnnotationsFileUpdater!!.updateAnnotations(jvmNames)
}
override fun revert() {
environment.kaptAnnotationsFileUpdater!!.revert()
}
}
IncrementalCompilerServicesFacade
@@ -1,442 +0,0 @@
/*
* Copyright 2010-2016 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 com.android.build.gradle.BaseExtension
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.UnknownDomainObjectException
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.compile.AbstractCompile
import org.gradle.api.tasks.compile.JavaCompile
//import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
//import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
//import com.intellij.lang.Language
//import com.intellij.openapi.util.Disposer
//import com.intellij.psi.PsiFileFactory
//import com.intellij.psi.PsiJavaFile
//import com.intellij.psi.impl.PsiFileFactoryImpl
//import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptionsImpl
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
import org.jetbrains.kotlin.gradle.tasks.kapt.generateAnnotationProcessorWrapper
import org.jetbrains.kotlin.gradle.tasks.kapt.generateKotlinAptAnnotation
import org.jetbrains.kotlin.gradle.tasks.isBuildCacheSupported
import java.io.File
import java.io.IOException
import java.util.zip.ZipFile
internal fun Project.initKapt(
kotlinTask: KotlinCompile,
javaTask: JavaCompile,
kaptManager: AnnotationProcessingManager,
variantName: String,
kotlinOptions: KotlinJvmOptionsImpl?,
subpluginEnvironment: SubpluginEnvironment,
tasksProvider: KotlinTasksProvider,
androidProjectHandler: AbstractAndroidProjectHandler<*>?
): KotlinCompile? {
val kaptExtension = extensions.getByType(KaptExtension::class.java)
val kotlinAfterJavaTask: KotlinCompile?
fun warnUnsupportedKapt1Option(optionName: String) {
kotlinTask.logger.kotlinWarn("'$optionName' option is not supported by this kapt implementation. " +
"Please add the \"apply plugin: 'kotlin-kapt\" line to your build script to enable it.")
}
if (kaptExtension.processors.isNotEmpty()) warnUnsupportedKapt1Option("processors")
if (kaptExtension.correctErrorTypes) warnUnsupportedKapt1Option("correctErrorTypes")
if (kaptExtension.generateStubs) {
kotlinAfterJavaTask = createKotlinAfterJavaTask(javaTask, kotlinTask, kotlinOptions, tasksProvider)
kotlinTask.logger.kotlinDebug("kapt: Using class file stubs")
val stubsDir = File(buildDir, "tmp/kapt/$variantName/classFileStubs").apply { mkdirs() }
kotlinAfterJavaTask.destinationDir = kotlinTask.destinationDir
kotlinTask.destinationDir = stubsDir
kotlinTask.kaptOptions.generateStubs = true
kotlinAfterJavaTask.source(kaptManager.generatedKotlinSourceDir)
kotlinAfterJavaTask.source(kaptManager.aptOutputDir)
subpluginEnvironment.addSubpluginOptions(this, kotlinAfterJavaTask, javaTask, null, androidProjectHandler, null)
// javaTask.doLast {
// moveGeneratedJavaFilesToCorrespondingDirectories(kaptManager.aptOutputDir)
// }
if (isBuildCacheSupported()) {
// Since Kapt1 is about to be dropped, disable the cache for it:
kotlinAfterJavaTask.outputs.doNotCacheIf("Caching is not supported with deprecated Kapt1") { true }
}
} else {
kotlinAfterJavaTask = null
kotlinTask.logger.kotlinDebug("kapt: Class file stubs are not used")
}
javaTask.appendClasspathDynamically(kaptManager.wrappersDirectory)
javaTask.source(kaptManager.hackAnnotationDir)
kotlinTask.kaptOptions.supportInheritedAnnotations = kaptExtension.inheritedAnnotations
kotlinTask.doFirst {
kaptManager.generateJavaHackFile()
}
javaTask.doFirst {
kaptManager.setupKapt()
kaptManager.generateJavaHackFile()
kotlinAfterJavaTask?.source(kaptManager.generatedKotlinSourceDir)
}
javaTask.doLast {
kaptManager.afterJavaCompile()
}
kotlinTask.kaptOptions.annotationsFile = kaptManager.getAnnotationFile()
if (isBuildCacheSupported()) {
// Since Kapt1 is about to be dropped, disable the cache for it:
kotlinTask.outputs.doNotCacheIf("Caching is not supported with deprecated Kapt1") { true }
}
return kotlinAfterJavaTask
}
private fun Project.createKotlinAfterJavaTask(
javaTask: AbstractCompile,
kotlinTask: KotlinCompile,
kotlinOptions: KotlinJvmOptionsImpl?,
tasksProvider: KotlinTasksProvider
): KotlinCompile {
val kotlinAfterJavaTask = with (tasksProvider.createKotlinJVMTask(this, kotlinTask.name + KOTLIN_AFTER_JAVA_TASK_SUFFIX, kotlinTask.sourceSetName)) {
mapClasspath { kotlinTask.classpath }
this
}
kotlinAfterJavaTask.dependsOn(javaTask)
javaTask.finalizedByIfNotFailed(kotlinAfterJavaTask)
kotlinAfterJavaTask.parentKotlinOptionsImpl = kotlinOptions
return kotlinAfterJavaTask
}
class AnnotationProcessingManager(
task: AbstractCompile,
private val javaTask: JavaCompile,
private val taskQualifier: String,
private val aptFiles: Set<File>,
val aptOutputDir: File,
private val aptWorkingDir: File,
private val androidVariant: Any? = null) {
private val project = task.project
val wrappersDirectory = File(aptWorkingDir, "wrappers")
val hackAnnotationDir = File(aptWorkingDir, "java_src")
private var originalJavaCompilerArgs: List<String>? = null
private var originalProcessorPath: FileCollection? = null
private companion object {
val JAVA_FQNAME_PATTERN = "^([\\p{L}_$][\\p{L}\\p{N}_$]*\\.)*[\\p{L}_$][\\p{L}\\p{N}_$]*$".toRegex()
val GEN_ANNOTATION = "__gen/annotation"
private val ANDROID_APT_PLUGIN_ID = "com.neenbedankt.android-apt"
}
fun getAnnotationFile(): File {
if (!aptWorkingDir.exists()) aptWorkingDir.mkdirs()
return File(wrappersDirectory, "annotations.$taskQualifier.txt")
}
val generatedKotlinSourceDir: File
get() {
val kotlinGeneratedDir = File(aptWorkingDir, "kotlinGenerated")
if (!kotlinGeneratedDir.exists()) kotlinGeneratedDir.mkdirs()
return kotlinGeneratedDir
}
val kaptProcessorPath get() = setOf(wrappersDirectory) + aptFiles + javaTask.classpath
private fun allowToUseOriginalKapt(): Boolean {
return project.hasProperty("allow.original.kapt")
&& project.property("allow.original.kapt").toString().toBoolean()
}
fun setupKapt() {
originalJavaCompilerArgs = javaTask.options.compilerArgs
if (aptFiles.isEmpty()) return
val deprecationMessage = "${project.name}: " +
"Original kapt is deprecated. Please add \"apply plugin: 'kotlin-kapt'\" to your build.gradle."
if (allowToUseOriginalKapt()) {
project.logger.warn(deprecationMessage)
} else {
throw GradleException(deprecationMessage)
}
if (project.plugins.findPlugin(ANDROID_APT_PLUGIN_ID) != null) {
project.logger.warn("Please do not use `$ANDROID_APT_PLUGIN_ID` with kapt.")
}
val annotationProcessorFqNames = lookupAnnotationProcessors(aptFiles)
generateAnnotationProcessorStubs(javaTask, annotationProcessorFqNames, wrappersDirectory)
setProcessorPathInJavaTask()
if (aptOutputDir.exists()) {
aptOutputDir.deleteRecursively()
}
addGeneratedSourcesOutputToCompilerArgs(javaTask, aptOutputDir)
appendAnnotationsArguments()
appendAdditionalComplerArgs()
}
fun afterJavaCompile() {
val generatedFile = File(javaTask.destinationDir, "$GEN_ANNOTATION/Cl.class")
if (generatedFile.exists()) {
generatedFile.delete()
} else {
project.logger.kotlinDebug("kapt: Java file stub was not found at $generatedFile")
}
javaTask.options.compilerArgs = originalJavaCompilerArgs
tryRevertProcessorPathProperty()
}
fun generateJavaHackFile() {
val javaHackPackageDir = File(hackAnnotationDir, GEN_ANNOTATION)
val javaHackClFile = File(javaHackPackageDir, "Cl.java")
if (!javaHackClFile.exists()) {
javaHackClFile.parentFile.mkdirs()
javaHackClFile.writeText("package __gen.annotation;\n" +
"class Cl { @__gen.KotlinAptAnnotation boolean v; }")
}
}
private fun appendAnnotationsArguments() {
javaTask.modifyCompilerArguments { list ->
list.add("-Akapt.annotations=" + getAnnotationFile())
list.add("-Akapt.kotlin.generated=" + generatedKotlinSourceDir)
}
}
private fun appendAdditionalComplerArgs() {
val kaptExtension = project.extensions.getByType(KaptExtension::class.java)
val args = kaptExtension.getAdditionalArgumentsForJavac(project, androidVariant, getAndroidExtension())
if (args.isEmpty()) return
javaTask.modifyCompilerArguments { list ->
list.addAll(args)
}
}
private fun generateAnnotationProcessorStubs(javaTask: JavaCompile, processorFqNames: Set<String>, outputDir: File) {
val aptAnnotationFile = generateKotlinAptAnnotation(outputDir)
project.logger.kotlinDebug("kapt: Stub annotation generated: $aptAnnotationFile")
val stubOutputPackageDir = File(outputDir, "__gen")
stubOutputPackageDir.mkdirs()
for (processorFqName in processorFqNames) {
val wrapperFile = generateAnnotationProcessorWrapper(
processorFqName,
"__gen",
stubOutputPackageDir,
getProcessorStubClassName(processorFqName),
taskQualifier)
project.logger.kotlinDebug("kapt: Wrapper for $processorFqName generated: $wrapperFile")
}
val annotationProcessorWrapperFqNames = processorFqNames
.map { fqName -> "__gen." + getProcessorStubClassName(fqName) }
.joinToString(",")
addWrappersToCompilerArgs(javaTask, annotationProcessorWrapperFqNames)
}
private fun addWrappersToCompilerArgs(javaTask: JavaCompile, wrapperFqNames: String) {
javaTask.addCompilerArgument("-processor") { prevValue ->
if (prevValue != null) "$prevValue,$wrapperFqNames" else wrapperFqNames
}
}
private fun getAndroidExtension(): BaseExtension? {
try {
return project.extensions.getByName("android") as BaseExtension
} catch (e: UnknownDomainObjectException) {
return null
}
}
private fun addGeneratedSourcesOutputToCompilerArgs(javaTask: JavaCompile, outputDir: File) {
outputDir.mkdirs()
javaTask.addCompilerArgument("-s") { prevValue ->
if (prevValue != null)
javaTask.logger.warn("Destination for generated sources was modified by kapt. Previous value = $prevValue")
outputDir.absolutePath
}
}
private fun setProcessorPathInJavaTask() {
val path = kaptProcessorPath
// If processor path property is supported, set it, otherwise set compiler argument:
val couldSetProperty = tryAppendProcessorPathProperty(path)
if (!couldSetProperty) {
javaTask.addCompilerArgument("-processorpath") { prevValue ->
if (prevValue != null)
javaTask.logger.warn("Processor path was modified by kapt. Previous value = $prevValue")
path.joinToString(postfix = prevValue?.let { File.pathSeparator + it }.orEmpty(),
separator = File.pathSeparator)
}
}
}
private fun tryAppendProcessorPathProperty(path: Iterable<File>): Boolean = try {
val optionsClass = javaTask.options.javaClass
val getPath = optionsClass.getMethod("getAnnotationProcessorPath")
val setPath = optionsClass.getMethod("setAnnotationProcessorPath", FileCollection::class.java)
originalProcessorPath = getPath(javaTask.options) as? FileCollection
if (originalProcessorPath != null)
javaTask.logger.warn("Processor path was modified by kapt. Previous value = $originalProcessorPath")
val newPath = javaTask.project.files(path + (originalProcessorPath ?: emptyList()))
setPath(javaTask.options, newPath)
true
} catch (_: NoSuchMethodException) {
false
}
private fun tryRevertProcessorPathProperty() {
try {
val optionsClass = javaTask.options.javaClass
val setPath = optionsClass.getMethod("setAnnotationProcessorPath", FileCollection::class.java)
setPath(javaTask.options, originalProcessorPath)
} catch (_: NoSuchMethodException) {
}
}
private fun getProcessorStubClassName(processorFqName: String): String {
return "AnnotationProcessorWrapper_${taskQualifier}_${processorFqName.replace('.', '_')}"
}
private inline fun JavaCompile.addCompilerArgument(name: String, value: (String?) -> String) {
modifyCompilerArguments { args ->
val argIndex = args.indexOfFirst { name == it }
if (argIndex >= 0 && args.size > (argIndex + 1)) {
args[argIndex + 1] = value(args[argIndex + 1])
}
else {
args.add(name)
args.add(value(null))
}
}
}
private inline fun JavaCompile.modifyCompilerArguments(modifier: (MutableList<String>) -> Unit) {
val compilerArgs: List<Any> = this.options.compilerArgs
val newCompilerArgs = compilerArgs.mapTo(arrayListOf<String>(), Any::toString)
modifier(newCompilerArgs)
options.compilerArgs = newCompilerArgs
}
private fun lookupAnnotationProcessors(files: Set<File>): Set<String> {
fun withZipFile(file: File, job: (ZipFile) -> Unit) {
var zipFile: ZipFile? = null
try {
zipFile = ZipFile(file)
job(zipFile)
}
catch (e: IOException) {
// Do nothing (do not continue to search for annotation processors on error)
}
catch (e: IllegalStateException) {
// ZipFile was already closed for some reason
}
finally {
try {
zipFile?.close()
}
catch (e: IOException) {}
}
}
val annotationProcessors = hashSetOf<String>()
fun processLines(lines: Sequence<String>) {
for (line in lines) {
if (line.isBlank() || !JAVA_FQNAME_PATTERN.matches(line)) continue
annotationProcessors.add(line)
}
}
for (file in files) {
withZipFile(file) { zipFile ->
val entry = zipFile.getEntry("META-INF/services/javax.annotation.processing.Processor")
if (entry != null) {
zipFile.getInputStream(entry).reader().useLines(::processLines)
}
}
}
project.logger.kotlinDebug("kapt: Discovered annotation processors: ${annotationProcessors.joinToString()}")
return annotationProcessors
}
}
// Java files can be generated anywhere, but
// Kotlin searches for java fq-name only in directory corresponding to package.
// Previously this worked because generated files were added to classpath.
// However in that case incremental compilation worked unreliable with generated files.
// The solution is to post-process generated java files and move them to corresponding packages
//fun moveGeneratedJavaFilesToCorrespondingDirectories(generatedJavaSourceRoot: File) {
// val javaFiles = generatedJavaSourceRoot.walk().filter { it.extension.equals("java", ignoreCase = true) }.toList()
//
// if (javaFiles.isEmpty()) return
//
// val rootDisposable = Disposer.newDisposable()
// val configuration = CompilerConfiguration()
// val environment = KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
// val project = environment.project
// val psiFileFactory = PsiFileFactory.getInstance(project) as PsiFileFactoryImpl
//
// for (javaFile in javaFiles) {
// val psiFile = psiFileFactory.createFileFromText(javaFile.nameWithoutExtension, Language.findLanguageByID("JAVA")!!, javaFile.readText())
// val packageName = (psiFile as? PsiJavaFile)?.packageName ?: continue
// val expectedDir = File(generatedJavaSourceRoot, packageName.replace('.', '/'))
// val expectedFile = File(expectedDir, javaFile.name)
//
// if (javaFile != expectedFile) {
// expectedFile.parentFile.mkdirs()
// javaFile.copyTo(expectedFile, overwrite = true)
// javaFile.delete()
// }
// }
//}
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2016 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.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.gradle.internal
@@ -59,7 +48,9 @@ class Kapt3GradleSubplugin : Plugin<Project> {
File(project.project.buildDir, "generated/source/kaptKotlin/$sourceSetName")
}
override fun apply(project: Project) {}
override fun apply(project: Project) {
project.extensions.create("kapt", KaptExtension::class.java)
}
}
abstract class KaptVariantData<T>(val variantData: T) {
@@ -170,6 +161,8 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
javaSourceSet.name
}
createAptConfigurationIfNeeded(project, sourceSetName)
val kaptExtension = project.extensions.getByType(KaptExtension::class.java)
val nonEmptyKaptConfigurations = kaptConfigurations.filter { configuration ->
@@ -196,6 +189,23 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
return emptyList()
}
private fun createAptConfigurationIfNeeded(project: Project, sourceSetName: String): Configuration {
val configurationName = Kapt3KotlinGradleSubplugin.getKaptConfigurationName(sourceSetName)
project.configurations.findByName(configurationName)?.let { return it }
val aptConfiguration = project.configurations.create(configurationName)
if (aptConfiguration.name != Kapt3KotlinGradleSubplugin.MAIN_KAPT_CONFIGURATION_NAME) {
// The main configuration can be created after the current one. We should handle this case
val mainConfiguration = findMainKaptConfiguration(project)
?: createAptConfigurationIfNeeded(project, SourceSet.MAIN_SOURCE_SET_NAME)
aptConfiguration.extendsFrom(mainConfiguration)
}
return aptConfiguration
}
override fun getSubpluginKotlinTasks(project: Project, kotlinCompile: KotlinCompile): List<AbstractCompile> {
val kaptGenerateStubsTask = kotlinToKaptGenerateStubsTasksMap[kotlinCompile]
return if (kaptGenerateStubsTask == null) emptyList() else listOf(kaptGenerateStubsTask)
@@ -2,7 +2,6 @@ package org.jetbrains.kotlin.gradle.plugin
import com.android.build.gradle.BaseExtension
import com.android.build.gradle.BasePlugin
import com.android.build.gradle.api.AndroidSourceSet
import com.android.builder.model.SourceProvider
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.text.StringUtil.compareVersionNumbers
@@ -37,7 +36,6 @@ import java.util.*
import java.util.concurrent.Callable
import java.util.jar.Manifest
val KOTLIN_AFTER_JAVA_TASK_SUFFIX = "AfterJava"
val KOTLIN_DSL_NAME = "kotlin"
val KOTLIN_JS_DSL_NAME = "kotlin2js"
val KOTLIN_OPTIONS_DSL_NAME = "kotlinOptions"
@@ -145,7 +143,6 @@ internal class Kotlin2JvmSourceSetProcessor(
tasksProvider.createKotlinJVMTask(project, taskName, sourceSet.name)
override fun doTargetSpecificProcessing() {
val aptConfiguration = project.createAptConfiguration(sourceSet.name, kotlinPluginVersion)
kotlinSourceSet.kotlin.source(sourceSet.java)
project.afterEvaluate { project ->
@@ -156,26 +153,11 @@ internal class Kotlin2JvmSourceSetProcessor(
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
project, kotlinTask, javaTask as JavaCompile, null, null, sourceSet)
var kotlinAfterJavaTask: KotlinCompile? = null
if (!Kapt3GradleSubplugin.isEnabled(project) && aptConfiguration.allDependencies.size > 1) {
javaTask.dependsOn(aptConfiguration.buildDependencies)
val (aptOutputDir, aptWorkingDir) = project.getAptDirsForSourceSet(sourceSetName)
val kaptManager = AnnotationProcessingManager(kotlinTask, javaTask, sourceSetName,
aptConfiguration.resolve(), aptOutputDir, aptWorkingDir)
kotlinAfterJavaTask = project.initKapt(kotlinTask, javaTask, kaptManager,
sourceSetName, null, subpluginEnvironment, tasksProvider, null)
} else {
removeAnnotationProcessingPluginClasspathEntry(kotlinTask)
}
removeAnnotationProcessingPluginClasspathEntry(kotlinTask)
// KotlinCompile.source(kotlinDirSet) should be called only after all java roots are added to kotlinDirSet
// otherwise some java roots can be ignored
kotlinTask.source(kotlinSourceSet.kotlin)
kotlinAfterJavaTask?.source(kotlinSourceSet.kotlin)
appliedPlugins
.flatMap { it.getSubpluginKotlinTasks(project, kotlinTask) }
.forEach { it.source(kotlinSourceSet.kotlin) }
@@ -185,12 +167,12 @@ internal class Kotlin2JvmSourceSetProcessor(
var syncOutputTask: SyncOutputTask? = null
if (!isSeparateClassesDirSupported) {
syncOutputTask = createSyncOutputTask(project, kotlinTask, javaTask, kotlinAfterJavaTask, sourceSetName)
syncOutputTask = createSyncOutputTask(project, kotlinTask, javaTask, sourceSetName)
}
if (project.pluginManager.hasPlugin("java-library") && sourceSetName == SourceSet.MAIN_SOURCE_SET_NAME) {
val (classesProviderTask, classesDirectory) = when {
isSeparateClassesDirSupported -> (kotlinAfterJavaTask ?: kotlinTask).let { it to it.destinationDir }
isSeparateClassesDirSupported -> kotlinTask.let { it to it.destinationDir }
else -> syncOutputTask!!.let { it to it.javaOutputDir }
}
@@ -421,7 +403,6 @@ internal open class KotlinPlugin(
Kotlin2JvmSourceSetProcessor(project, javaBasePlugin, sourceSet, tasksProvider, kotlinSourceSetProvider, kotlinPluginVersion)
override fun apply(project: Project) {
project.createKaptExtension()
project.pluginManager.apply(ScriptingGradleSubplugin::class.java)
super.apply(project)
}
@@ -509,8 +490,7 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
androidExt: BaseExtension,
variantData: V,
javaTask: AbstractCompile,
kotlinTask: KotlinCompile,
kotlinAfterJavaTask: KotlinCompile?): Unit
kotlinTask: KotlinCompile)
protected abstract fun wrapVariantDataForKapt(variantData: V): KaptVariantData<V>
@@ -523,16 +503,12 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
val kotlinSourceSet = kotlinConfigurationTools.kotlinSourceSetProvider.create(sourceSet.name)
kotlinSourceSet.kotlin.srcDir(project.file(project.file("src/${sourceSet.name}/kotlin")))
sourceSet.addConvention(KOTLIN_DSL_NAME, kotlinSourceSet)
aptConfigurations.put(sourceSet.name, project.createAptConfiguration(sourceSet.name, kotlinConfigurationTools.kotlinPluginVersion))
}
val kotlinOptions = KotlinJvmOptionsImpl()
kotlinOptions.noJdk = true
ext.addExtension(KOTLIN_OPTIONS_DSL_NAME, kotlinOptions)
project.createKaptExtension()
project.afterEvaluate { project ->
if (project != null) {
val androidPluginIds = listOf("android", "com.android.application", "android-library", "com.android.library",
@@ -585,49 +561,10 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
kotlinTask.destinationDir = File(project.buildDir, "tmp/kotlin-classes/$variantDataName")
kotlinTask.description = "Compiles the $variantDataName kotlin."
val isKapt3Enabled = Kapt3GradleSubplugin.isEnabled(project)
removeAnnotationProcessingPluginClasspathEntry(kotlinTask)
val aptFiles = arrayListOf<File>()
if (!isKapt3Enabled) {
var hasAnyKaptDependency: Boolean = false
for (provider in getSourceProviders(variantData)) {
val aptConfiguration = aptConfigurations[(provider as AndroidSourceSet).name]
// Ignore if there's only an annotation processor wrapper in dependencies (added by default)
if (aptConfiguration != null && aptConfiguration.allDependencies.size > 1) {
javaTask.dependsOn(aptConfiguration.buildDependencies)
aptFiles.addAll(aptConfiguration.resolve())
hasAnyKaptDependency = true
}
}
if (!hasAnyKaptDependency) {
removeAnnotationProcessingPluginClasspathEntry(kotlinTask)
}
} else {
removeAnnotationProcessingPluginClasspathEntry(kotlinTask)
}
var kotlinAfterJavaTask: KotlinCompile? = null
if (javaTask is JavaCompile && aptFiles.isNotEmpty() && !isKapt3Enabled) {
val (aptOutputDir, aptWorkingDir) = project.getAptDirsForSourceSet(variantDataName)
addJavaSourceDirectoryToVariantModel(variantData, aptOutputDir)
val kaptManager = AnnotationProcessingManager(kotlinTask, javaTask, variantDataName,
aptFiles.toSet(), aptOutputDir, aptWorkingDir, variantData)
kotlinAfterJavaTask = project.initKapt(kotlinTask, javaTask, kaptManager,
variantDataName, rootKotlinOptions, subpluginEnvironment, tasksProvider, this)
}
for (task in listOfNotNull(kotlinTask, kotlinAfterJavaTask)) {
configureSources(task, variantData)
}
wireKotlinTasks(project, androidPlugin, androidExt, variantData, javaTask,
kotlinTask, kotlinAfterJavaTask)
configureSources(kotlinTask, variantData)
wireKotlinTasks(project, androidPlugin, androidExt, variantData, javaTask, kotlinTask)
val appliedPlugins = subpluginEnvironment.addSubpluginOptions(
project, kotlinTask, javaTask, wrapVariantDataForKapt(variantData), this, null)
@@ -680,8 +617,6 @@ internal fun configureJavaTask(kotlinTask: KotlinCompile, javaTask: AbstractComp
}
}
// Also, use kapt1 annotations file for up-to-date check since annotation processing is done with javac
kotlinTask.kaptOptions.annotationsFile?.let { javaTask.inputsCompatible.fileCompatible(it) }
javaTask.dependsOn(kotlinTask)
/*
* It's important to modify javaTask.classpath only in doFirst,
@@ -698,13 +633,10 @@ internal fun syncOutputTaskName(variantName: String) = "copy${variantName.capita
internal fun createSyncOutputTask(
project: Project,
kotlinTask: KotlinCompile,
kotlinCompile: KotlinCompile,
javaTask: AbstractCompile,
kotlinAfterJavaTask: KotlinCompile?,
variantName: String
): SyncOutputTask {
// if kotlinAfterJavaTask is not null then kotlinTask compiles stubs, so don't sync them
val kotlinCompile = kotlinAfterJavaTask ?: kotlinTask
val kotlinDir = kotlinCompile.destinationDir
val javaDir = javaTask.destinationDir
val taskName = syncOutputTaskName(variantName)
@@ -713,13 +645,11 @@ internal fun createSyncOutputTask(
syncTask.kotlinOutputDir = kotlinDir
syncTask.javaOutputDir = javaDir
syncTask.kotlinTask = kotlinCompile
kotlinTask.javaOutputDir = javaDir
kotlinAfterJavaTask?.javaOutputDir = javaDir
kotlinCompile.javaOutputDir = javaDir
syncTask.kaptClassesDir = getKaptGeneratedClassesDir(project, variantName)
// copying should be executed after a latter task
val previousTask = kotlinAfterJavaTask ?: javaTask
previousTask.finalizedByIfNotFailed(syncTask)
javaTask.finalizedByIfNotFailed(syncTask)
project.logger.kotlinDebug { "Created task ${syncTask.path} to copy kotlin classes from $kotlinDir to $javaDir" }
@@ -734,12 +664,12 @@ private val KOTLIN_ANNOTATION_PROCESSING_FILE_REGEX = "kotlin-annotation-process
private fun removeAnnotationProcessingPluginClasspathEntry(kotlinCompile: KotlinCompile) {
kotlinCompile.pluginOptions.classpath
.map(::File)
.filter { it.name.matches(KOTLIN_ANNOTATION_PROCESSING_FILE_REGEX) }
.forEach {
kotlinCompile.logger.kotlinDebug("Removing plugin classpath dependency $it")
kotlinCompile.pluginOptions.removeClasspathEntry(it)
}
.map(::File)
.filter { it.name.matches(KOTLIN_ANNOTATION_PROCESSING_FILE_REGEX) }
.forEach {
kotlinCompile.logger.kotlinDebug("Removing plugin classpath dependency $it")
kotlinCompile.pluginOptions.removeClasspathEntry(it)
}
}
private fun loadSubplugins(project: Project): SubpluginEnvironment {
@@ -847,41 +777,6 @@ internal fun Task.registerSubpluginOptionsAsInputs(subpluginId: String, subplugi
}
}
private fun Project.getAptDirsForSourceSet(sourceSetName: String): Pair<File, File> {
val aptOutputDir = File(buildDir, "generated/source/kapt")
val aptOutputDirForVariant = File(aptOutputDir, sourceSetName)
val aptWorkingDir = File(buildDir, "tmp/kapt")
val aptWorkingDirForVariant = File(aptWorkingDir, sourceSetName)
return aptOutputDirForVariant to aptWorkingDirForVariant
}
private fun Project.createAptConfiguration(sourceSetName: String, kotlinPluginVersion: String): Configuration {
val aptConfigurationName = Kapt3KotlinGradleSubplugin.getKaptConfigurationName(sourceSetName)
configurations.findByName(aptConfigurationName)?.let { return it }
val aptConfiguration = configurations.create(aptConfigurationName)
// Add base kotlin-annotation-processing artifact for the main kapt configuration,
// All other configurations (such as kaptTest) should extend the main one
if (aptConfiguration.name == Kapt3KotlinGradleSubplugin.MAIN_KAPT_CONFIGURATION_NAME) {
val kotlinAnnotationProcessingDep = "org.jetbrains.kotlin:kotlin-annotation-processing-gradle:$kotlinPluginVersion"
aptConfiguration.dependencies.add(dependencies.create(kotlinAnnotationProcessingDep))
} else {
// "main" configuration can be created after some other. We should handle this case
val mainConfiguration = Kapt3KotlinGradleSubplugin.findMainKaptConfiguration(this)
?: createAptConfiguration("main", kotlinPluginVersion)
aptConfiguration.extendsFrom(mainConfiguration)
}
return aptConfiguration
}
private fun Project.createKaptExtension() {
extensions.create("kapt", KaptExtension::class.java)
}
//copied from BasePlugin.getLocalVersion
internal fun loadAndroidPluginVersion(): String? {
try {
@@ -1,3 +1,8 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.gradle.plugin
import com.android.build.gradle.BaseExtension
@@ -40,8 +45,7 @@ internal class LegacyAndroidAndroidProjectHandler(kotlinConfigurationTools: Kotl
androidExt: BaseExtension,
variantData: BaseVariantData<out BaseVariantOutputData>,
javaTask: AbstractCompile,
kotlinTask: KotlinCompile,
kotlinAfterJavaTask: KotlinCompile?
kotlinTask: KotlinCompile
) {
kotlinTask.dependsOn(*javaTask.dependsOn.toTypedArray())
@@ -56,7 +60,7 @@ internal class LegacyAndroidAndroidProjectHandler(kotlinConfigurationTools: Kotl
}
configureJavaTask(kotlinTask, javaTask, logger)
createSyncOutputTask(project, kotlinTask, javaTask, kotlinAfterJavaTask, getVariantName(variantData))
createSyncOutputTask(project, kotlinTask, javaTask, getVariantName(variantData))
// In lib modules, the androidTest variants get the classes jar in their classpath instead of the Java
// destination dir. Attach the JAR to be consumed as friend path:
@@ -1,25 +0,0 @@
/*
* Copyright 2010-2016 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.tasks
import java.io.File
class KaptOptions {
var supportInheritedAnnotations: Boolean = false
var generateStubs: Boolean = false
var annotationsFile: File? = null
}
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2016 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.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.gradle.tasks
@@ -26,8 +15,6 @@ import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.compile.AbstractCompile
import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.api.tasks.incremental.IncrementalTaskInputs
import org.jetbrains.kotlin.annotation.AnnotationFileUpdater
import org.jetbrains.kotlin.annotation.AnnotationFileUpdaterImpl
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments
@@ -231,9 +218,6 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
compilerCalled = true
callCompiler(args, sourceRoots, ChangedFiles(inputs))
}
@Internal
@@ -283,11 +267,6 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
@get:Internal
internal open val sourceRootsContainer = FilteringSourceRootsContainer()
private var kaptAnnotationsFileUpdater: AnnotationFileUpdater? = null
@get:Internal
val kaptOptions = KaptOptions()
/** A package prefix that is used for locating Java sources in a directory structure with non-full-depth packages.
*
* Example: a Java source file with `package com.example.my.package` is located in directory `src/main/java/my/package`.
@@ -315,9 +294,7 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
override fun setupPlugins(compilerArgs: K2JVMCompilerArguments) {
compilerArgs.pluginClasspaths = pluginClasspath.toTypedArray()
val kaptPluginOptions = getKaptPluginOptions()
compilerArgs.pluginOptions = (pluginOptions.arguments + kaptPluginOptions.arguments).toTypedArray()
compilerArgs.pluginOptions = pluginOptions.arguments.toTypedArray()
}
override fun setupCompilerArgs(args: K2JVMCompilerArguments, defaultsOnly: Boolean) {
@@ -366,7 +343,7 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
computedCompilerClasspath,
if (hasFilesInTaskBuildDirectory()) changedFiles else ChangedFiles.Unknown(),
taskBuildDirectory,
messageCollector, outputItemCollector, args, kaptAnnotationsFileUpdater,
messageCollector, outputItemCollector, args,
usePreciseJavaTracking = usePreciseJavaTracking,
localStateDirs = outputDirectories,
multiModuleICSettings = multiModuleICSettings
@@ -429,25 +406,6 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
throwGradleExceptionIfError(exitCode)
}
private fun getKaptPluginOptions() =
CompilerPluginOptions().apply {
kaptOptions.annotationsFile?.let { kaptAnnotationsFile ->
if (incremental) {
kaptAnnotationsFileUpdater = AnnotationFileUpdaterImpl(kaptAnnotationsFile)
}
addPluginArgument(ANNOTATIONS_PLUGIN_NAME, FilesSubpluginOption("output", listOf(kaptAnnotationsFile)))
}
if (kaptOptions.generateStubs) {
addPluginArgument(ANNOTATIONS_PLUGIN_NAME, FilesSubpluginOption("stubs", listOf(destinationDir)))
}
if (kaptOptions.supportInheritedAnnotations) {
addPluginArgument(ANNOTATIONS_PLUGIN_NAME, SubpluginOption("inherited", true.toString()))
}
}
// override setSource to track source directory sets and files (for generated android folders)
override fun setSource(sources: Any?) {
sourceRootsContainer.set(sources)