Remove source annotations removing (not needed with KAPT3)
This commit is contained in:
-68
@@ -1,68 +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.incremental.components.SourceRetentionAnnotationHandler
|
||||
import java.io.*
|
||||
import java.util.*
|
||||
|
||||
internal class SourceAnnotationsRegistry(private val file: File) : SourceRetentionAnnotationHandler {
|
||||
private val mutableAnnotations: MutableSet<String> by lazy { readAnnotations() }
|
||||
val annotations: Set<String>
|
||||
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<String> {
|
||||
val result = HashSet<String>()
|
||||
|
||||
if (!file.exists()) return result
|
||||
|
||||
ObjectInputStream(BufferedInputStream(file.inputStream())).use { input ->
|
||||
val size = input.readInt()
|
||||
repeat(size) {
|
||||
result.add(input.readUTF())
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
-78
@@ -1,78 +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.bytecode
|
||||
|
||||
import org.jetbrains.org.objectweb.asm.*
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
internal class AnnotationsRemover(annotations: Iterable<String>) {
|
||||
private val annotations = annotations.mapTo(HashSet()) { "L$it;" }
|
||||
|
||||
fun transformClassFile(inputFile: File, outputFile: File) {
|
||||
assert(inputFile.extension.toLowerCase() == "class") { "Expected class file: $inputFile" }
|
||||
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<out String>?): 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()
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -62,7 +62,7 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
|
||||
}
|
||||
|
||||
private val kotlinToKaptTasksMap = mutableMapOf<KotlinCompile, KaptTask>()
|
||||
|
||||
|
||||
override fun isApplicable(project: Project, task: KotlinCompile) = Kapt3GradleSubplugin.isEnabled(project)
|
||||
|
||||
fun getKaptGeneratedDir(project: Project, sourceSetName: String): File {
|
||||
|
||||
+1
-14
@@ -23,7 +23,6 @@ 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
|
||||
@@ -58,12 +57,6 @@ internal open class SyncOutputTask : DefaultTask() {
|
||||
var kotlinOutputDir: File by Delegates.notNull()
|
||||
var javaOutputDir: File by Delegates.notNull()
|
||||
var kotlinTask: KotlinCompile by Delegates.notNull()
|
||||
private val sourceAnnotations: Set<String> by lazy {
|
||||
kotlinTask.sourceAnnotationsRegistry?.annotations ?: emptySet()
|
||||
}
|
||||
private val annotationsRemover by lazy {
|
||||
AnnotationsRemover(sourceAnnotations)
|
||||
}
|
||||
|
||||
// OutputDirectory needed for task to be incremental
|
||||
@get:OutputDirectory
|
||||
@@ -144,13 +137,7 @@ internal open class SyncOutputTask : DefaultTask() {
|
||||
if (!fileInKotlinDir.isFile) return
|
||||
|
||||
fileInJavaDir.parentFile.mkdirs()
|
||||
if (sourceAnnotations.isNotEmpty() && fileInKotlinDir.extension.toLowerCase() == "class") {
|
||||
logger.kotlinDebug { "Removing source annotations from class: $fileInKotlinDir" }
|
||||
annotationsRemover.transformClassFile(fileInKotlinDir, fileInJavaDir)
|
||||
}
|
||||
else {
|
||||
fileInKotlinDir.copyTo(fileInJavaDir, overwrite = true)
|
||||
}
|
||||
fileInKotlinDir.copyTo(fileInJavaDir, overwrite = true)
|
||||
|
||||
timestamps[fileInJavaDir] = fileInJavaDir.lastModified()
|
||||
|
||||
|
||||
-4
@@ -27,7 +27,6 @@ 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.cli.common.CLICompiler
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||
@@ -165,8 +164,6 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
|
||||
internal val pluginOptions = CompilerPluginOptions()
|
||||
internal var artifactDifferenceRegistryProvider: ArtifactDifferenceRegistryProvider? = null
|
||||
internal var artifactFile: File? = null
|
||||
// created only if kapt2 is active
|
||||
internal var sourceAnnotationsRegistry: SourceAnnotationsRegistry? = null
|
||||
|
||||
override fun findKotlinCompilerJar(project: Project): File? =
|
||||
findKotlinJvmCompilerJar(project)
|
||||
@@ -227,7 +224,6 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
|
||||
cacheVersions,
|
||||
reporter,
|
||||
kaptAnnotationsFileUpdater,
|
||||
sourceAnnotationsRegistry,
|
||||
artifactDifferenceRegistryProvider,
|
||||
artifactFile
|
||||
)
|
||||
|
||||
+1
-5
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import org.jetbrains.kotlin.annotation.AnnotationFileUpdater
|
||||
import org.jetbrains.kotlin.annotation.SourceAnnotationsRegistry
|
||||
import org.jetbrains.kotlin.build.GeneratedFile
|
||||
import org.jetbrains.kotlin.build.GeneratedJvmClass
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||
@@ -97,7 +96,6 @@ internal class IncrementalJvmCompilerRunner(
|
||||
private val cacheVersions: List<CacheVersion>,
|
||||
private val reporter: IncReporter,
|
||||
private var kaptAnnotationsFileUpdater: AnnotationFileUpdater? = null,
|
||||
private val sourceAnnotationsRegistry: SourceAnnotationsRegistry? = null,
|
||||
private val artifactDifferenceRegistryProvider: ArtifactDifferenceRegistryProvider? = null,
|
||||
private val artifactFile: File? = null
|
||||
) {
|
||||
@@ -394,7 +392,6 @@ internal class IncrementalJvmCompilerRunner(
|
||||
}
|
||||
|
||||
if (exitCode == ExitCode.OK) {
|
||||
sourceAnnotationsRegistry?.flush()
|
||||
cacheVersions.forEach { it.saveIfNeeded() }
|
||||
}
|
||||
|
||||
@@ -462,7 +459,6 @@ internal class IncrementalJvmCompilerRunner(
|
||||
val outputItemCollector = OutputItemsCollectorImpl()
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val messageCollector = MessageCollectorWrapper(messageCollector, outputItemCollector)
|
||||
sourceAnnotationsRegistry?.clear()
|
||||
|
||||
try {
|
||||
val incrementalCaches = makeIncrementalCachesMap(targets, { listOf<TargetId>() }, getIncrementalCache, { this })
|
||||
@@ -473,7 +469,7 @@ internal class IncrementalJvmCompilerRunner(
|
||||
|
||||
reporter.report { "compiling with args: ${ArgumentUtils.convertArgumentsToStringList(args)}" }
|
||||
reporter.report { "compiling with classpath: ${classpath.toList().sorted().joinToString()}" }
|
||||
val compileServices = makeCompileServices(incrementalCaches, lookupTracker, compilationCanceledStatus, sourceAnnotationsRegistry)
|
||||
val compileServices = makeCompileServices(incrementalCaches, lookupTracker, compilationCanceledStatus)
|
||||
val exitCode = compiler.exec(messageCollector, compileServices, args)
|
||||
val generatedFiles = outputItemCollector.generatedFiles(targets, targets.first(), {sourcesToCompile}, {outputDir})
|
||||
reporter.reportCompileIteration(sourcesToCompile, exitCode)
|
||||
|
||||
-108
@@ -1,108 +0,0 @@
|
||||
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, "-Xadd-compiler-builtins")
|
||||
}
|
||||
|
||||
if (exitCode != ExitCode.OK) {
|
||||
System.err.print(byteOut.toString())
|
||||
}
|
||||
|
||||
assertEquals(ExitCode.OK, exitCode)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user