Kapt: Remove kapt1 support from Gradle and incremental compilation
This commit is contained in:
+1
-13
@@ -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,
|
||||
|
||||
-35
@@ -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()
|
||||
}
|
||||
}
|
||||
-37
@@ -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()
|
||||
}
|
||||
|
||||
+5
-21
@@ -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,
|
||||
|
||||
+2
-17
@@ -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)
|
||||
|
||||
-46
@@ -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)
|
||||
}
|
||||
}
|
||||
+5
-2
@@ -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
|
||||
|
||||
+7
-18
@@ -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
|
||||
-442
@@ -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()
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
+24
-14
@@ -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)
|
||||
|
||||
+16
-121
@@ -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 {
|
||||
|
||||
+7
-3
@@ -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:
|
||||
|
||||
-25
@@ -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
|
||||
}
|
||||
+4
-46
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user