diff --git a/build-common/src/org/jetbrains/kotlin/incremental/IncrementalCompilationComponentsImpl.kt b/build-common/src/org/jetbrains/kotlin/incremental/IncrementalCompilationComponentsImpl.kt index d8bca1fae5f..2d0ef506d3e 100644 --- a/build-common/src/org/jetbrains/kotlin/incremental/IncrementalCompilationComponentsImpl.kt +++ b/build-common/src/org/jetbrains/kotlin/incremental/IncrementalCompilationComponentsImpl.kt @@ -24,13 +24,10 @@ import org.jetbrains.kotlin.modules.TargetId class IncrementalCompilationComponentsImpl( private val caches: Map, - private val lookupTracker: LookupTracker, - private val sourceRetentionAnnotationHandler: SourceRetentionAnnotationHandler? + private val lookupTracker: LookupTracker ): IncrementalCompilationComponents { override fun getIncrementalCache(target: TargetId): IncrementalCache = caches[target] ?: throw Exception("Incremental cache for target ${target.name} not found") override fun getLookupTracker(): LookupTracker = lookupTracker - - override fun getSourceRetentionAnnotationHandler() = sourceRetentionAnnotationHandler } diff --git a/build-common/src/org/jetbrains/kotlin/incremental/buildUtil.kt b/build-common/src/org/jetbrains/kotlin/incremental/buildUtil.kt index 754500aa009..9e7e5154220 100644 --- a/build-common/src/org/jetbrains/kotlin/incremental/buildUtil.kt +++ b/build-common/src/org/jetbrains/kotlin/incremental/buildUtil.kt @@ -67,24 +67,21 @@ fun makeModuleFile(name: String, isTest: Boolean, outputDir: File, sourcesToComp return scriptFile } -fun makeCompileServices( - incrementalCaches: Map, - lookupTracker: LookupTracker, - compilationCanceledStatus: CompilationCanceledStatus? -) = makeCompileServices(incrementalCaches, lookupTracker, compilationCanceledStatus, null) - fun makeCompileServices( incrementalCaches: Map, lookupTracker: LookupTracker, compilationCanceledStatus: CompilationCanceledStatus?, - sourceRetentionAnnotationHandler: SourceRetentionAnnotationHandler? + sourceRetentionAnnotationHandler: SourceRetentionAnnotationHandler? = null ): Services = with(Services.Builder()) { register(IncrementalCompilationComponents::class.java, - IncrementalCompilationComponentsImpl(incrementalCaches, lookupTracker, sourceRetentionAnnotationHandler)) + IncrementalCompilationComponentsImpl(incrementalCaches, lookupTracker)) compilationCanceledStatus?.let { register(CompilationCanceledStatus::class.java, it) } + sourceRetentionAnnotationHandler?.let { + register(SourceRetentionAnnotationHandler::class.java, it) + } build() } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt index 165bb7d2234..b2fca041d77 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt @@ -37,6 +37,7 @@ import org.jetbrains.kotlin.compiler.plugin.CliOptionProcessingException import org.jetbrains.kotlin.compiler.plugin.PluginCliOptionProcessingException import org.jetbrains.kotlin.compiler.plugin.cliPluginUsageString import org.jetbrains.kotlin.config.* +import org.jetbrains.kotlin.incremental.components.SourceRetentionAnnotationHandler import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents @@ -300,6 +301,10 @@ class K2JVMCompiler : CLICompiler() { configuration.put(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS, components) } } + + services.get(SourceRetentionAnnotationHandler::class.java)?.let { handler -> + configuration.put(JVMConfigurationKeys.SOURCE_RETENTION_ANNOTATION_HANDLER, handler) + } } /** diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/RemoteIncrementalCompilationComponentsClient.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/RemoteIncrementalCompilationComponentsClient.kt index 8feb68a6872..bd353d09432 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/RemoteIncrementalCompilationComponentsClient.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/RemoteIncrementalCompilationComponentsClient.kt @@ -32,6 +32,4 @@ class RemoteIncrementalCompilationComponentsClient(val facade: CompilerCallbackS override fun getIncrementalCache(target: TargetId): IncrementalCache = RemoteIncrementalCacheClient(facade, target, profiler) override fun getLookupTracker(): LookupTracker = remoteLookupTrackerClient - - override fun getSourceRetentionAnnotationHandler() = null } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java b/compiler/frontend.java/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java index d4f145ede8a..8f98f9827f2 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.config; +import org.jetbrains.kotlin.incremental.components.SourceRetentionAnnotationHandler; import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents; import org.jetbrains.kotlin.modules.Module; import org.jetbrains.kotlin.script.KotlinScriptDefinition; @@ -64,6 +65,9 @@ public class JVMConfigurationKeys { public static final CompilerConfigurationKey MODULE_XML_FILE = CompilerConfigurationKey.create("path to module.xml"); + public static final CompilerConfigurationKey SOURCE_RETENTION_ANNOTATION_HANDLER = + CompilerConfigurationKey.create("source retention annotation handler"); + public static final CompilerConfigurationKey DECLARATIONS_JSON_PATH = CompilerConfigurationKey.create("path to declarations output"); diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/components/IncrementalCompilationComponents.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/components/IncrementalCompilationComponents.kt index e73b82cd84f..ac5292941cc 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/components/IncrementalCompilationComponents.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/components/IncrementalCompilationComponents.kt @@ -23,5 +23,4 @@ import org.jetbrains.kotlin.modules.TargetId interface IncrementalCompilationComponents { fun getIncrementalCache(target: TargetId): IncrementalCache fun getLookupTracker(): LookupTracker - fun getSourceRetentionAnnotationHandler(): SourceRetentionAnnotationHandler? } diff --git a/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt b/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt index 55f18273a40..6a57f769cb3 100644 --- a/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt +++ b/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt @@ -414,16 +414,20 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) { sourceRetentionAnnotationHandler: SourceRetentionAnnotationHandler?, context: CompileContext ): CompilerEnvironment { - val compilerServices = Services.Builder() - .register(IncrementalCompilationComponents::class.java, - IncrementalCompilationComponentsImpl(incrementalCaches.mapKeys { TargetId(it.key) }, - lookupTracker, sourceRetentionAnnotationHandler)) - .register(CompilationCanceledStatus::class.java, object : CompilationCanceledStatus { - override fun checkCanceled() { - if (context.cancelStatus.isCanceled) throw CompilationCanceledException() - } - }) - .build() + val compilerServices = with(Services.Builder()) { + register(IncrementalCompilationComponents::class.java, + IncrementalCompilationComponentsImpl(incrementalCaches.mapKeys { TargetId(it.key) }, + lookupTracker)) + register(CompilationCanceledStatus::class.java, object : CompilationCanceledStatus { + override fun checkCanceled() { + if (context.cancelStatus.isCanceled) throw CompilationCanceledException() + } + }) + sourceRetentionAnnotationHandler?.let { + register(SourceRetentionAnnotationHandler::class.java, it) + } + build() + } return CompilerEnvironment.getEnvironmentFor( PathUtil.getKotlinPathsForJpsPluginOrJpsTests(), diff --git a/libraries/examples/kotlin-gradle-subplugin-example/src/main/kotlin/example/ExampleSubplugin.kt b/libraries/examples/kotlin-gradle-subplugin-example/src/main/kotlin/example/ExampleSubplugin.kt index 5e56e511ac6..6b7b8bb2383 100644 --- a/libraries/examples/kotlin-gradle-subplugin-example/src/main/kotlin/example/ExampleSubplugin.kt +++ b/libraries/examples/kotlin-gradle-subplugin-example/src/main/kotlin/example/ExampleSubplugin.kt @@ -22,7 +22,7 @@ import org.gradle.api.tasks.SourceSet import org.gradle.api.tasks.compile.AbstractCompile import org.jetbrains.kotlin.gradle.plugin.SubpluginOption -class ExampleSubplugin : KotlinGradleSubplugin { +class ExampleSubplugin : KotlinGradleSubplugin { override fun isApplicable(project: Project, task: AbstractCompile): Boolean { return true diff --git a/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinGradleSubplugin.kt b/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinGradleSubplugin.kt index 7a91a259d33..a9fc4224f4e 100644 --- a/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinGradleSubplugin.kt +++ b/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinGradleSubplugin.kt @@ -22,12 +22,12 @@ import org.gradle.api.tasks.compile.AbstractCompile class SubpluginOption(val key: String, val value: String) -interface KotlinGradleSubplugin { - fun isApplicable(project: Project, task: AbstractCompile): Boolean +interface KotlinGradleSubplugin { + fun isApplicable(project: Project, task: KotlinCompile): Boolean fun apply( project: Project, - kotlinCompile: AbstractCompile, + kotlinCompile: KotlinCompile, javaCompile: AbstractCompile, variantData: Any?, javaSourceSet: SourceSet? diff --git a/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/annotation/SourceAnnotationsRegistry.kt b/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/annotation/SourceAnnotationsRegistry.kt new file mode 100644 index 00000000000..7b26c683d2d --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/annotation/SourceAnnotationsRegistry.kt @@ -0,0 +1,52 @@ +package org.jetbrains.kotlin.annotation + +import org.jetbrains.kotlin.incremental.components.SourceRetentionAnnotationHandler +import java.io.* +import java.util.* + +class SourceAnnotationsRegistry(private val file: File) : SourceRetentionAnnotationHandler { + private val mutableAnnotations: MutableSet by lazy { readAnnotations() } + val annotations: Set + get() = mutableAnnotations + + override fun register(internalName: String) { + mutableAnnotations.add(internalName) + } + + fun clear() { + mutableAnnotations.clear() + file.delete() + } + + fun flush() { + if (mutableAnnotations.isEmpty()) { + file.delete() + return + } + + if (!file.exists()) { + file.parentFile.mkdirs() + file.createNewFile() + } + + ObjectOutputStream(BufferedOutputStream(file.outputStream())).use { out -> + out.writeInt(mutableAnnotations.size) + mutableAnnotations.forEach { out.writeUTF(it) } + } + } + + private fun readAnnotations(): MutableSet { + val result = HashSet() + + if (!file.exists()) return result + + ObjectInputStream(BufferedInputStream(file.inputStream())).use { input -> + val size = input.readInt() + repeat(size) { + result.add(input.readUTF()) + } + } + + return result + } +} diff --git a/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt b/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt index 67e1c827f85..5e52acaa763 100644 --- a/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt +++ b/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt @@ -12,6 +12,7 @@ import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.api.tasks.incremental.IncrementalTaskInputs import org.jetbrains.kotlin.annotation.AnnotationFileUpdater +import org.jetbrains.kotlin.annotation.SourceAnnotationsRegistry import org.jetbrains.kotlin.build.GeneratedFile import org.jetbrains.kotlin.cli.common.CLICompiler import org.jetbrains.kotlin.cli.common.ExitCode @@ -41,6 +42,7 @@ import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.incremental.* import org.jetbrains.kotlin.incremental.components.LookupTracker +import org.jetbrains.kotlin.incremental.components.SourceRetentionAnnotationHandler import org.jetbrains.kotlin.modules.TargetId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.progress.CompilationCanceledStatus @@ -153,7 +155,7 @@ open class KotlinCompile() : AbstractKotlinCompile() { private val sourceRoots = HashSet() // lazy because name is probably not available when constructor is called - private val taskBuildDirectory: File by lazy { File(File(project.buildDir, KOTLIN_BUILD_DIR_NAME), name) } + val taskBuildDirectory: File by lazy { File(File(project.buildDir, KOTLIN_BUILD_DIR_NAME), name) } private val cacheDirectory: File by lazy { File(taskBuildDirectory, CACHES_DIR_NAME) } private val dirtySourcesSinceLastTimeFile: File by lazy { File(taskBuildDirectory, DIRTY_SOURCES_FILE_NAME) } private val lastBuildInfoFile: File by lazy { File(taskBuildDirectory, LAST_BUILD_INFO_FILE_NAME) } @@ -180,6 +182,8 @@ open class KotlinCompile() : AbstractKotlinCompile() { val pluginOptions = CompilerPluginOptions() var artifactDifferenceRegistry: ArtifactDifferenceRegistry? = null var artifactFile: File? = null + // created only if kapt2 is active + var sourceAnnotationsRegistry: SourceAnnotationsRegistry? = null override fun populateTargetSpecificArgs(args: K2JVMCompilerArguments) { logger.kotlinDebug("args.freeArgs = ${args.freeArgs}") @@ -413,6 +417,7 @@ open class KotlinCompile() : AbstractKotlinCompile() { ExitCode.INTERNAL_ERROR -> throw GradleException("Internal compiler error. See log for more details") ExitCode.SCRIPT_EXECUTION_ERROR -> throw GradleException("Script execution error. See log for more details") ExitCode.OK -> { + sourceAnnotationsRegistry?.flush() cacheVersions.forEach { it.saveIfNeeded() } logger.kotlinInfo("Compilation succeeded") } @@ -540,6 +545,7 @@ open class KotlinCompile() : AbstractKotlinCompile() { args.module = moduleFile.absolutePath val outputItemCollector = OutputItemsCollectorImpl() val messageCollector = GradleMessageCollector(logger, outputItemCollector) + sourceAnnotationsRegistry?.clear() try { val incrementalCaches = makeIncrementalCachesMap(targets, { listOf() }, getIncrementalCache, { this }) @@ -549,7 +555,8 @@ open class KotlinCompile() : AbstractKotlinCompile() { } logger.kotlinDebug("compiling with args ${ArgumentUtils.convertArgumentsToStringList(args)}") - val exitCode = compiler.exec(messageCollector, makeCompileServices(incrementalCaches, lookupTracker, compilationCanceledStatus), args) + val compileServices = makeCompileServices(incrementalCaches, lookupTracker, compilationCanceledStatus, sourceAnnotationsRegistry) + val exitCode = compiler.exec(messageCollector, compileServices, args) return CompileChangedResults( exitCode, outputItemCollector.generatedFiles( @@ -584,9 +591,17 @@ open class KotlinCompile() : AbstractKotlinCompile() { args.module = moduleFile.absolutePath val messageCollector = GradleMessageCollector(logger) + sourceAnnotationsRegistry?.clear() + val services = with (Services.Builder()) { + sourceAnnotationsRegistry?.let { handler -> + register(SourceRetentionAnnotationHandler::class.java, handler) + } + build() + } + try { logger.kotlinDebug("compiling with args ${ArgumentUtils.convertArgumentsToStringList(args)}") - return compiler.exec(messageCollector, Services.EMPTY, args) + return compiler.exec(messageCollector, services, args) } finally { moduleFile.delete() diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/bytecode/AnnotationsRemover.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/bytecode/AnnotationsRemover.kt new file mode 100644 index 00000000000..50335c0cef0 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/bytecode/AnnotationsRemover.kt @@ -0,0 +1,61 @@ +package org.jetbrains.kotlin.bytecode + +import org.jetbrains.org.objectweb.asm.* +import java.io.File +import java.util.* + +class AnnotationsRemover(annotations: Iterable) { + private val annotations = annotations.mapTo(HashSet()) { "L$it;" } + + fun transformClassFile(inputFile: File, outputFile: File) { + val bytes = inputFile.readBytes() + val reader = ClassReader(bytes) + val classWriter = ClassWriter(0) + val visitor = ClassAnnotationRemover(classWriter) + reader.accept(visitor, 0) + outputFile.writeBytes(classWriter.toByteArray()) + } + + inner class ClassAnnotationRemover(classVisitor: ClassVisitor) : ClassVisitor(Opcodes.ASM5, classVisitor) { + override fun visitAnnotation(desc: String?, visible: Boolean): AnnotationVisitor? = + checkAnnotation(desc) { super.visitAnnotation(desc, visible) } + + override fun visitTypeAnnotation(typeRef: Int, typePath: TypePath?, desc: String?, visible: Boolean): AnnotationVisitor? = + checkAnnotation(desc) { super.visitTypeAnnotation(typeRef, typePath, desc, visible) } + + override fun visitMethod(access: Int, name: String?, desc: String?, signature: String?, exceptions: Array?): MethodVisitor { + val methodVisitor = super.visitMethod(access, name, desc, signature, exceptions) + return MethodAnnotationRemover(methodVisitor) + } + + override fun visitField(access: Int, name: String?, desc: String?, signature: String?, value: Any?): FieldVisitor { + val fieldVisitor = super.visitField(access, name, desc, signature, value) + return FieldAnnotationRemover(fieldVisitor) + } + } + + inner class MethodAnnotationRemover(methodVisitor: MethodVisitor) : MethodVisitor(Opcodes.ASM5, methodVisitor) { + override fun visitAnnotation(desc: String?, visible: Boolean): AnnotationVisitor? = + checkAnnotation(desc) { super.visitAnnotation(desc, visible) } + + override fun visitTypeAnnotation(typeRef: Int, typePath: TypePath?, desc: String?, visible: Boolean): AnnotationVisitor? = + checkAnnotation(desc) { super.visitTypeAnnotation(typeRef, typePath, desc, visible) } + + override fun visitParameterAnnotation(parameter: Int, desc: String?, visible: Boolean): AnnotationVisitor? = + checkAnnotation(desc) { super.visitParameterAnnotation(parameter, desc, visible) } + } + + inner class FieldAnnotationRemover(fieldVisitor: FieldVisitor) : FieldVisitor(Opcodes.ASM5, fieldVisitor) { + override fun visitAnnotation(desc: String?, visible: Boolean): AnnotationVisitor? = + checkAnnotation(desc) { super.visitAnnotation(desc, visible) } + + override fun visitTypeAnnotation(typeRef: Int, typePath: TypePath?, desc: String?, visible: Boolean): AnnotationVisitor? = + checkAnnotation(desc) { super.visitTypeAnnotation(typeRef, typePath, desc, visible) } + } + + private inline fun checkAnnotation(desc: String?, default: () -> AnnotationVisitor?): AnnotationVisitor? { + if (desc in annotations) return null + + return default() + } +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/AndroidSubplugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/AndroidSubplugin.kt index 0ffc32b1213..80e3fdc4fc2 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/AndroidSubplugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/AndroidSubplugin.kt @@ -26,6 +26,7 @@ import org.gradle.api.tasks.compile.AbstractCompile import org.jetbrains.kotlin.gradle.plugin.KotlinGradleSubplugin import org.jetbrains.kotlin.gradle.plugin.SubpluginOption import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.w3c.dom.Document import java.io.File import javax.xml.parsers.DocumentBuilderFactory @@ -36,13 +37,13 @@ class AndroidExtensionsSubpluginIndicator : Plugin { override fun apply(target: Project?) {} } -class AndroidSubplugin : KotlinGradleSubplugin { +class AndroidSubplugin : KotlinGradleSubplugin { private companion object { @Volatile var migrateWarningReported: Boolean = false } - override fun isApplicable(project: Project, task: AbstractCompile): Boolean { + override fun isApplicable(project: Project, task: KotlinCompile): Boolean { try { project.extensions.getByName("android") as? BaseExtension ?: return false } catch (e: UnknownDomainObjectException) { @@ -61,7 +62,7 @@ class AndroidSubplugin : KotlinGradleSubplugin { override fun apply( project: Project, - kotlinCompile: AbstractCompile, + kotlinCompile: KotlinCompile, javaCompile: AbstractCompile, variantData: Any?, javaSourceSet: SourceSet? diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt2KotlinGradleSubplugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt2KotlinGradleSubplugin.kt index 10e7c090bb8..874784bc2af 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt2KotlinGradleSubplugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt2KotlinGradleSubplugin.kt @@ -25,9 +25,11 @@ import org.gradle.api.artifacts.Configuration import org.gradle.api.tasks.SourceSet import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.api.tasks.compile.JavaCompile +import org.jetbrains.kotlin.annotation.SourceAnnotationsRegistry import org.jetbrains.kotlin.gradle.plugin.KaptExtension import org.jetbrains.kotlin.gradle.plugin.KotlinGradleSubplugin import org.jetbrains.kotlin.gradle.plugin.SubpluginOption +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import java.io.File // apply plugin: 'kotlin-kapt2' @@ -40,7 +42,7 @@ class Kapt2GradleSubplugin : Plugin { } // Subplugin for the Kotlin Gradle plugin -class Kapt2KotlinGradleSubplugin : KotlinGradleSubplugin { +class Kapt2KotlinGradleSubplugin : KotlinGradleSubplugin { companion object { private val VERBOSE_OPTION_NAME = "kapt.verbose" @@ -49,7 +51,7 @@ class Kapt2KotlinGradleSubplugin : KotlinGradleSubplugin { } } - override fun isApplicable(project: Project, task: AbstractCompile) = Kapt2GradleSubplugin.isEnabled(project) + override fun isApplicable(project: Project, task: KotlinCompile) = Kapt2GradleSubplugin.isEnabled(project) fun getKaptGeneratedDir(project: Project, sourceSetName: String): File { return File(project.project.buildDir, "generated/source/kapt2/$sourceSetName") @@ -61,7 +63,7 @@ class Kapt2KotlinGradleSubplugin : KotlinGradleSubplugin { override fun apply( project: Project, - kotlinCompile: AbstractCompile, + kotlinCompile: KotlinCompile, javaCompile: AbstractCompile, variantData: Any?, javaSourceSet: SourceSet? @@ -121,7 +123,10 @@ class Kapt2KotlinGradleSubplugin : KotlinGradleSubplugin { if (project.hasProperty(VERBOSE_OPTION_NAME) && project.property(VERBOSE_OPTION_NAME) == "true") { pluginOptions += SubpluginOption("verbose", "true") } - + + val annotationsFile = File(kotlinCompile.taskBuildDirectory, "source-annotations.txt") + kotlinCompile.sourceAnnotationsRegistry = SourceAnnotationsRegistry(annotationsFile) + val incrementalCompilationDataFile = File(project.buildDir, "tmp/kapt2/$sourceSetName/incrementalData.txt") pluginOptions += SubpluginOption("incrementalData", incrementalCompilationDataFile.absolutePath) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt index f566f769111..9c1b29c181d 100755 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt @@ -459,13 +459,15 @@ private fun createSyncOutputTask( variantName: String ) { // if kotlinAfterJavaTask is not null then kotlinTask compiles stubs, so don't sync them - val kotlinDir = (kotlinAfterJavaTask ?: kotlinTask).destinationDir + val kotlinCompile = kotlinAfterJavaTask ?: kotlinTask + val kotlinDir = kotlinCompile.destinationDir val javaDir = javaTask.destinationDir val taskName = "copy${variantName.capitalize()}KotlinClasses" val syncTask = project.tasks.create(taskName, SyncOutputTask::class.java) syncTask.kotlinOutputDir = kotlinDir syncTask.javaOutputDir = javaDir + syncTask.kotlinTask = kotlinCompile kotlinTask.javaOutputDir = javaDir kotlinAfterJavaTask?.javaOutputDir = javaDir @@ -478,7 +480,8 @@ private fun createSyncOutputTask( private fun loadSubplugins(project: Project): SubpluginEnvironment { try { - val subplugins = ServiceLoader.load(KotlinGradleSubplugin::class.java, project.buildscript.classLoader).toList() + val subplugins = ServiceLoader.load(KotlinGradleSubplugin::class.java, project.buildscript.classLoader) + .map { @Suppress("UNCHECKED_CAST") (it as KotlinGradleSubplugin) } fun Project.getResolvedArtifacts() = buildscript.configurations.getByName("classpath") .resolvedConfiguration.resolvedArtifacts @@ -489,7 +492,7 @@ private fun loadSubplugins(project: Project): SubpluginEnvironment { resolvedClasspathArtifacts += rootProject.getResolvedArtifacts() } - val subpluginClasspaths = hashMapOf>() + val subpluginClasspaths = hashMapOf, List>() for (subplugin in subplugins) { val file = resolvedClasspathArtifacts @@ -511,8 +514,8 @@ private fun loadSubplugins(project: Project): SubpluginEnvironment { } class SubpluginEnvironment( - val subpluginClasspaths: Map>, - val subplugins: List + val subpluginClasspaths: Map, List>, + val subplugins: List> ) { fun addSubpluginArguments( diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/SyncOutputTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/SyncOutputTask.kt index 3398599de25..7fbe6f83778 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/SyncOutputTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/SyncOutputTask.kt @@ -23,10 +23,11 @@ import org.gradle.api.tasks.OutputFiles import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.incremental.IncrementalTaskInputs import org.gradle.api.tasks.incremental.InputFileDetails +import org.jetbrains.kotlin.bytecode.AnnotationsRemover import org.jetbrains.kotlin.gradle.plugin.kotlinDebug -import java.io.File -import java.io.ObjectInputStream -import java.io.ObjectOutputStream +import org.jetbrains.kotlin.incremental.md5 +import org.jetbrains.org.objectweb.asm.* +import java.io.* import java.util.* import kotlin.properties.Delegates @@ -56,6 +57,11 @@ open class SyncOutputTask : DefaultTask() { @get:InputFiles var kotlinOutputDir: File by Delegates.notNull() var javaOutputDir: File by Delegates.notNull() + var kotlinTask: KotlinCompile by Delegates.notNull() + private val sourceAnnotations: Set by lazy { + kotlinTask.sourceAnnotationsRegistry?.annotations ?: emptySet() + } + private val annotationsRemover by lazy { AnnotationsRemover(sourceAnnotations) } // OutputDirectory needed for task to be incremental @get:OutputDirectory @@ -130,7 +136,13 @@ open class SyncOutputTask : DefaultTask() { if (!fileInKotlinDir.isFile) return fileInJavaDir.parentFile.mkdirs() - fileInKotlinDir.copyTo(fileInJavaDir, overwrite = true) + if (sourceAnnotations.isEmpty()) { + fileInKotlinDir.copyTo(fileInJavaDir, overwrite = true) + } + else { + annotationsRemover.transformClassFile(fileInKotlinDir, fileInJavaDir) + } + timestamps[fileInJavaDir] = fileInJavaDir.lastModified() logger.kotlinDebug { diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/bytecode/AnnotationsRemoverTest.kt b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/bytecode/AnnotationsRemoverTest.kt new file mode 100644 index 00000000000..ef603853718 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/bytecode/AnnotationsRemoverTest.kt @@ -0,0 +1,108 @@ +package org.jetbrains.kotlin.bytecode + +import org.jetbrains.kotlin.cli.common.ExitCode +import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler +import org.jetbrains.kotlin.com.intellij.openapi.util.io.FileUtil.createTempDirectory +import org.jetbrains.kotlin.gradle.util.checkBytecodeContains +import org.jetbrains.kotlin.gradle.util.checkBytecodeNotContains +import org.junit.After +import org.junit.Test + +import org.junit.Assert.* +import org.junit.Before +import java.io.* +import kotlin.properties.Delegates + +class AnnotationsRemoverTest { + private var workingDir: File by Delegates.notNull() + + @Before + fun setUp() { + workingDir = createTempDirectory(AnnotationsRemoverTest::class.java.simpleName, null) + } + + @After + fun tearDown() { + workingDir.deleteRecursively() + } + + @Test + fun testRemoveAnnotations() { + // initial build + val sourceDir = File(workingDir, "src").apply { mkdirs() } + val annotationsKt = File(sourceDir, "annotations.kt").apply { + writeText(""" + package foo + + annotation class Ann1 + annotation class Ann2 + annotation class Ann3 + annotation class Ann4 + annotation class Ann5 + annotation class NotRemovableAnn1 + annotation class NotRemovableAnn2 + annotation class NotRemovableAnn3 + annotation class NotRemovableAnn4 + annotation class NotRemovableAnn5 + """.trimIndent()) + } + File(sourceDir, "A.kt").apply { + writeText(""" + import foo.* + + @Ann1 + @NotRemovableAnn1 + class A { + @get:Ann2 + @field:Ann3 + @get:NotRemovableAnn2 + @field:NotRemovableAnn3 + val i = 10 + + @Ann4 + @NotRemovableAnn4 + fun m(@Ann5 @NotRemovableAnn5 x: Int) {} + } + """.trimIndent()) + } + val annClassRegex = "annotation class (Ann\\d)".toRegex() + val annotationsToRemove = annClassRegex.findAll(annotationsKt.readText()).toList().map { "foo/${it.groupValues[1]}" } + assertEquals(5, annotationsToRemove.size) + + val notRemovableAnnClassRegex = "annotation class (NotRemovableAnn\\d)".toRegex() + val notRemovableAnns = notRemovableAnnClassRegex.findAll(annotationsKt.readText()).toList().map { "foo/${it.groupValues[1]}" } + assertEquals(5, notRemovableAnns.size) + + val outDir = File(workingDir, "out").apply { mkdirs() } + compileAll(sourceDir, outDir) + val aClass = File(outDir, "A.class") + assert(aClass.exists()) { "$aClass does not exist" } + checkBytecodeContains(aClass, annotationsToRemove) + + // remove annotations + val transformedOut = File(workingDir, "transformed").apply { mkdirs() } + val aTransformedClass = File(transformedOut, "A.class") + val remover = AnnotationsRemover(annotationsToRemove) + remover.transformClassFile(aClass, aTransformedClass) + checkBytecodeNotContains(aTransformedClass, annotationsToRemove) + checkBytecodeContains(aTransformedClass, notRemovableAnns) + } + + private fun compileAll(inputDir: File, outputDir: File) { + val ktFiles = inputDir.walk() + .filter { it.isFile && it.extension.toLowerCase() == "kt" } + .map { it.absolutePath } + .toList().toTypedArray() + + val byteOut = ByteArrayOutputStream() + val exitCode = PrintStream(byteOut).use { err -> + K2JVMCompiler().exec(err, *ktFiles, "-d", outputDir.absolutePath) + } + + if (exitCode != ExitCode.OK) { + System.err.print(byteOut.toString()) + } + + assertEquals(ExitCode.OK, exitCode) + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt index 854089196fc..2bbff218815 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt @@ -3,6 +3,7 @@ package org.jetbrains.kotlin.gradle import org.gradle.api.logging.LogLevel import org.jetbrains.kotlin.com.intellij.openapi.util.io.FileUtil import org.jetbrains.kotlin.gradle.plugin.KotlinGradleBuildServices +import org.jetbrains.kotlin.gradle.util.checkBytecodeNotContains import org.jetbrains.kotlin.gradle.util.createGradleCommand import org.jetbrains.kotlin.gradle.util.runProcess import org.junit.After @@ -162,6 +163,14 @@ abstract class BaseGradleIT { return this } + fun CompiledProject.assertClassFilesNotContain(dir: File, vararg strings: String) { + val classFiles = dir.walk().filter { it.isFile && it.extension.toLowerCase() == "class" } + + for (cf in classFiles) { + checkBytecodeNotContains(cf, strings.toList()) + } + } + fun CompiledProject.assertSubstringCount(substring: String, expectedCount: Int) { val actualCount = Pattern.quote(substring).toRegex().findAll(output).count() assertEquals(expectedCount, actualCount, "Number of occurrences in output for substring '$substring'") diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt2IT.kt b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt2IT.kt index b4386c24203..ea130a4cb65 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt2IT.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt2IT.kt @@ -16,10 +16,9 @@ package org.jetbrains.kotlin.gradle -import org.jetbrains.kotlin.gradle.util.getFileByName +import org.jetbrains.kotlin.gradle.util.* import org.junit.Test import java.io.File -import java.io.FileFilter class Kapt2IT: BaseGradleIT() { companion object { @@ -56,6 +55,7 @@ class Kapt2IT: BaseGradleIT() { assertFileExists("build/classes/main/example/BinaryAnnotatedTestClassGenerated.class") assertFileExists("build/classes/main/example/RuntimeAnnotatedTestClassGenerated.class") assertContains("example.JavaTest PASSED") + assertClassFilesNotContain(File(project.projectDir, "build/classes"), "ExampleSourceAnnotation") } project.build("build") { @@ -69,24 +69,32 @@ class Kapt2IT: BaseGradleIT() { fun testSimpleWithIC() { val options = defaultBuildOptions().copy(incremental = true) val project = Project("simple", GRADLE_VERSION, directoryPrefix = "kapt2") + val classesDir = File(project.projectDir, "build/classes") project.build("build", options = options) { assertSuccessful() assertKaptSuccessful() assertContains(":compileKotlin") assertContains(":compileJava") + assertClassFilesNotContain(classesDir, "ExampleSourceAnnotation") } - val files = listOf("InternalDummy.kt", "test.kt") - kotlin.repeat(2) { i -> - project.projectDir.getFileByName(files[i]).appendText(" ") + project.projectDir.getFilesByNames("InternalDummy.kt", "test.kt").forEach { it.appendText(" ") } + project.build("build", options = options) { + assertSuccessful() + assertKaptSuccessful() + assertContains(":compileKotlin") + assertContains(":compileJava") + assertClassFilesNotContain(classesDir, "ExampleSourceAnnotation") + } - project.build("build", options = options) { - assertSuccessful() - assertKaptSuccessful() - assertContains(":compileKotlin") - assertContains(":compileJava") - } + // emulating wipe by android plugin's IncrementalSafeguardTask + classesDir.deleteRecursively() + project.build("build", options = options) { + assertSuccessful() + assertContains(":compileKotlin UP-TO-DATE") + assertFileExists("build/classes/main/example/TestClass.class") + assertClassFilesNotContain(classesDir, "ExampleSourceAnnotation") } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/KaptIT.kt b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/KaptIT.kt index 1a57da8d82e..fac75a2caa5 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/KaptIT.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/KaptIT.kt @@ -4,6 +4,7 @@ import org.jetbrains.kotlin.gradle.util.allJavaFiles import org.jetbrains.kotlin.gradle.util.getFileByName import org.jetbrains.kotlin.gradle.util.modify import org.junit.Test +import java.io.File class KaptIT: BaseGradleIT() { @@ -32,6 +33,7 @@ class KaptIT: BaseGradleIT() { assertFileExists("build/classes/main/example/RuntimeAnnotatedTestClassGenerated.class") assertContains("example.JavaTest PASSED") assertContains("example.KotlinTest PASSED") + assertClassFilesNotContain(File(project.projectDir, "build/classes"), "ExampleSourceAnnotation") } // clean build is important diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/util/bytecodeUtils.kt b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/util/bytecodeUtils.kt new file mode 100644 index 00000000000..e7d6812924d --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/util/bytecodeUtils.kt @@ -0,0 +1,28 @@ +package org.jetbrains.kotlin.gradle.util + +import org.jetbrains.org.objectweb.asm.ClassReader +import org.jetbrains.org.objectweb.asm.util.TraceClassVisitor +import java.io.File +import java.io.PrintWriter +import java.io.StringWriter + +fun classFileBytecodeString(classFile: File): String { + val out = StringWriter() + val traceVisitor = TraceClassVisitor(PrintWriter(out)) + ClassReader(classFile.readBytes()).accept(traceVisitor, 0) + return out.toString() +} + +fun checkBytecodeContains(classFile: File, strings: Iterable) { + val bytecode = classFileBytecodeString(classFile) + for (string in strings) { + assert(bytecode.contains(string)) { "Bytecode should contain '$string':\n$bytecode" } + } +} + +fun checkBytecodeNotContains(classFile: File, strings: Iterable) { + val bytecode = classFileBytecodeString(classFile) + for (string in strings) { + assert(!bytecode.contains(string)) { "Bytecode should NOT contain '$string':\n$bytecode" } + } +} \ No newline at end of file diff --git a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingExtension.kt b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingExtension.kt index c0837b8b422..8a1f43b65b1 100755 --- a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingExtension.kt +++ b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingExtension.kt @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.config.APPEND_JAVA_SOURCE_ROOTS_HANDLER_KEY import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider +import org.jetbrains.kotlin.incremental.components.SourceRetentionAnnotationHandler import org.jetbrains.kotlin.java.model.elements.JeTypeElement import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents @@ -51,10 +52,10 @@ class ClasspathBasedAnnotationProcessingExtension( javaSourceRoots: List, verboseOutput: Boolean, incrementalDataFile: File?, - incrementalCompilationComponents: IncrementalCompilationComponents? + sourceRetentionAnnotationHandler: SourceRetentionAnnotationHandler? ) : AbstractAnnotationProcessingExtension(generatedSourcesOutputDir, classesOutputDir, javaSourceRoots, verboseOutput, - incrementalDataFile, incrementalCompilationComponents) { + incrementalDataFile, sourceRetentionAnnotationHandler) { override fun loadAnnotationProcessors(): List { val classLoader = URLClassLoader(annotationProcessingClasspath.map { it.toURI().toURL() }.toTypedArray()) return ServiceLoader.load(Processor::class.java, classLoader).toList() @@ -67,7 +68,7 @@ abstract class AbstractAnnotationProcessingExtension( val javaSourceRoots: List, val verboseOutput: Boolean, val incrementalDataFile: File? = null, - val incrementalCompilationComponents: IncrementalCompilationComponents? = null + val sourceRetentionAnnotationHandler: SourceRetentionAnnotationHandler? = null ) : AnalysisCompletedHandlerExtension { private companion object { val LINE_SEPARATOR = System.getProperty("line.separator") ?: "\n" @@ -170,7 +171,7 @@ abstract class AbstractAnnotationProcessingExtension( } val firstRoundAnnotations = RoundAnnotations( - incrementalCompilationComponents?.getSourceRetentionAnnotationHandler(), + sourceRetentionAnnotationHandler, bindingContext, createTypeMapper()) diff --git a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingPlugin.kt b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingPlugin.kt index ce4e1ecb31b..11689af8597 100755 --- a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingPlugin.kt +++ b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingPlugin.kt @@ -122,11 +122,11 @@ class AnnotationProcessingComponentRegistrar : ComponentRegistrar { // Annotations with the "SOURCE" retention will be written to class files project.putUserData(IS_KAPT2_ENABLED_KEY, true) - val incrementalCompilationComponents = configuration[JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS] + val sourceRetentionAnnotationHandler = configuration[JVMConfigurationKeys.SOURCE_RETENTION_ANNOTATION_HANDLER] val annotationProcessingExtension = ClasspathBasedAnnotationProcessingExtension( classpath, generatedOutputDirFile, classesOutputDir, javaRoots, verboseOutput, - incrementalDataFile, incrementalCompilationComponents) + incrementalDataFile, sourceRetentionAnnotationHandler) AnalysisCompletedHandlerExtension.registerExtension(project, annotationProcessingExtension) } diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/AbstractProcessorTest.kt b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/AbstractProcessorTest.kt index ee2018d031c..69785c22b89 100755 --- a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/AbstractProcessorTest.kt +++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/AbstractProcessorTest.kt @@ -43,7 +43,7 @@ import javax.lang.model.element.* class AnnotationProcessingExtensionForTests( val processors: List ) : AbstractAnnotationProcessingExtension(createTempDir(), createTempDir(), listOf(), true, - createIncrementalDataFile(), StubIncrementalCompilationComponents()) { + createIncrementalDataFile(), SourceRetentionAnnotationHandlerImpl()) { override fun loadAnnotationProcessors() = processors private companion object { @@ -55,14 +55,6 @@ class AnnotationProcessingExtensionForTests( deleteOnExit() } } - - private class StubIncrementalCompilationComponents : IncrementalCompilationComponents { - private val sourceRetentionAnnotationHandler = SourceRetentionAnnotationHandlerImpl() - - override fun getIncrementalCache(target: TargetId) = null!! - override fun getLookupTracker() = null!! - override fun getSourceRetentionAnnotationHandler() = sourceRetentionAnnotationHandler - } } abstract class AbstractProcessorTest : AbstractBytecodeTextTest() { diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/ProcessorTests.kt b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/ProcessorTests.kt index e9593a62694..c91d2400584 100644 --- a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/ProcessorTests.kt +++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/ProcessorTests.kt @@ -233,10 +233,8 @@ class ProcessorTests : AbstractProcessorTest() { fun testSourceRetention() { test("SourceRetention", "*") { set, roundEnv, env -> } val ext = getKapt2Extension() - val incrementalCompilationComponents = ext.incrementalCompilationComponents - assertNotNull(incrementalCompilationComponents) - val annotationHandler = incrementalCompilationComponents!!.getSourceRetentionAnnotationHandler() - val annotations = (annotationHandler as SourceRetentionAnnotationHandlerImpl).sourceRetentionAnnotations.sorted() + val annotationHandler = ext.sourceRetentionAnnotationHandler as SourceRetentionAnnotationHandlerImpl + val annotations = annotationHandler.sourceRetentionAnnotations.sorted() assertEquals("Source1, Source2, Source3, Source4, Test5\$Source5", annotations.joinToString()) }