Kapt: Annotations on enum constants are not kept on the generated stub (KT-21433)
This commit is contained in:
committed by
Yan Zhulanow
parent
c6f922fb64
commit
4c96453a4b
@@ -18,7 +18,11 @@ package org.jetbrains.kotlin.kapt3
|
|||||||
|
|
||||||
import com.intellij.ide.ClassUtilCore
|
import com.intellij.ide.ClassUtilCore
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.sun.tools.javac.code.Flags
|
||||||
import com.sun.tools.javac.tree.JCTree
|
import com.sun.tools.javac.tree.JCTree
|
||||||
|
import com.sun.tools.javac.tree.Pretty
|
||||||
|
import com.sun.tools.javac.tree.TreeMaker
|
||||||
|
import com.sun.tools.javac.util.Context
|
||||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||||
import org.jetbrains.kotlin.backend.common.output.OutputFile
|
import org.jetbrains.kotlin.backend.common.output.OutputFile
|
||||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.OUTPUT
|
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.OUTPUT
|
||||||
@@ -44,6 +48,8 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
|||||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||||
import org.jetbrains.kotlin.resolve.jvm.extensions.PartialAnalysisHandlerExtension
|
import org.jetbrains.kotlin.resolve.jvm.extensions.PartialAnalysisHandlerExtension
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.StringWriter
|
||||||
|
import java.io.Writer
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.annotation.processing.Processor
|
import javax.annotation.processing.Processor
|
||||||
@@ -264,7 +270,7 @@ abstract class AbstractKapt3Extension(
|
|||||||
logger.info { "Java stub generation took $stubGenerationTime ms" }
|
logger.info { "Java stub generation took $stubGenerationTime ms" }
|
||||||
logger.info { "Stubs for Kotlin classes: " + kotlinSourceStubs.joinToString { it.sourcefile.name } }
|
logger.info { "Stubs for Kotlin classes: " + kotlinSourceStubs.joinToString { it.sourcefile.name } }
|
||||||
|
|
||||||
saveStubs(kotlinSourceStubs)
|
saveStubs(kaptContext, kotlinSourceStubs)
|
||||||
saveIncrementalData(kaptContext, logger.messageCollector, converter)
|
saveIncrementalData(kaptContext, logger.messageCollector, converter)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,14 +283,14 @@ abstract class AbstractKapt3Extension(
|
|||||||
return javaFilesFromJavaSourceRoots
|
return javaFilesFromJavaSourceRoots
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun saveStubs(stubs: JavacList<JCTree.JCCompilationUnit>) {
|
protected open fun saveStubs(kaptContext: KaptContext<*>, stubs: JavacList<JCTree.JCCompilationUnit>) {
|
||||||
for (stub in stubs) {
|
for (stub in stubs) {
|
||||||
val className = (stub.defs.first { it is JCTree.JCClassDecl } as JCTree.JCClassDecl).simpleName.toString()
|
val className = (stub.defs.first { it is JCTree.JCClassDecl } as JCTree.JCClassDecl).simpleName.toString()
|
||||||
|
|
||||||
val packageName = stub.getPackageNameJava9Aware()?.toString() ?: ""
|
val packageName = stub.getPackageNameJava9Aware()?.toString() ?: ""
|
||||||
val packageDir = if (packageName.isEmpty()) stubsOutputDir else File(stubsOutputDir, packageName.replace('.', '/'))
|
val packageDir = if (packageName.isEmpty()) stubsOutputDir else File(stubsOutputDir, packageName.replace('.', '/'))
|
||||||
packageDir.mkdirs()
|
packageDir.mkdirs()
|
||||||
File(packageDir, className + ".java").writeText(stub.toString())
|
File(packageDir, className + ".java").writeText(stub.prettyPrint(kaptContext.context))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,6 +320,25 @@ abstract class AbstractKapt3Extension(
|
|||||||
protected abstract fun loadProcessors(): List<Processor>
|
protected abstract fun loadProcessors(): List<Processor>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun JCTree.prettyPrint(context: Context): String {
|
||||||
|
return StringWriter().apply { PrettyWithWorkarounds(context, this, false).printStat(this@prettyPrint) }.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PrettyWithWorkarounds(private val context: Context, out: Writer?, sourceOutput: Boolean) : Pretty(out, sourceOutput) {
|
||||||
|
companion object {
|
||||||
|
private val ENUM = Flags.ENUM.toLong()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitVarDef(tree: JCTree.JCVariableDecl) {
|
||||||
|
if ((tree.mods.flags and ENUM) != 0L) {
|
||||||
|
// Pretty does not print annotations for enum values for some reason
|
||||||
|
printExpr(TreeMaker.instance(context).Modifiers(0, tree.mods.annotations))
|
||||||
|
}
|
||||||
|
|
||||||
|
super.visitVarDef(tree)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private inline fun <T> measureTimeMillis(block: () -> T) : Pair<Long, T> {
|
private inline fun <T> measureTimeMillis(block: () -> T) : Pair<Long, T> {
|
||||||
val start = System.currentTimeMillis()
|
val start = System.currentTimeMillis()
|
||||||
val result = block()
|
val result = block()
|
||||||
|
|||||||
+4
-3
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.config.CompilerConfiguration
|
|||||||
import org.jetbrains.kotlin.kapt3.AbstractKapt3Extension
|
import org.jetbrains.kotlin.kapt3.AbstractKapt3Extension
|
||||||
import org.jetbrains.kotlin.kapt3.AptMode.STUBS_AND_APT
|
import org.jetbrains.kotlin.kapt3.AptMode.STUBS_AND_APT
|
||||||
import org.jetbrains.kotlin.kapt3.Kapt3BuilderFactory
|
import org.jetbrains.kotlin.kapt3.Kapt3BuilderFactory
|
||||||
|
import org.jetbrains.kotlin.kapt3.prettyPrint
|
||||||
import org.jetbrains.kotlin.kapt3.KaptContext
|
import org.jetbrains.kotlin.kapt3.KaptContext
|
||||||
import org.jetbrains.kotlin.kapt3.javac.KaptJavaFileObject
|
import org.jetbrains.kotlin.kapt3.javac.KaptJavaFileObject
|
||||||
import org.jetbrains.kotlin.kapt3.stubs.ClassFileToSourceStubConverter
|
import org.jetbrains.kotlin.kapt3.stubs.ClassFileToSourceStubConverter
|
||||||
@@ -170,17 +171,17 @@ abstract class AbstractKotlinKapt3IntegrationTest : CodegenTestCase() {
|
|||||||
|
|
||||||
override fun loadProcessors() = processors
|
override fun loadProcessors() = processors
|
||||||
|
|
||||||
override fun saveStubs(stubs: JavacList<JCTree.JCCompilationUnit>) {
|
override fun saveStubs(kaptContext: KaptContext<*>, stubs: JavacList<JCTree.JCCompilationUnit>) {
|
||||||
if (this.savedStubs != null) {
|
if (this.savedStubs != null) {
|
||||||
error("Stubs are already saved")
|
error("Stubs are already saved")
|
||||||
}
|
}
|
||||||
|
|
||||||
this.savedStubs = stubs
|
this.savedStubs = stubs
|
||||||
.map { it.toString() }
|
.map { it.prettyPrint(kaptContext.context) }
|
||||||
.sorted()
|
.sorted()
|
||||||
.joinToString(AbstractKotlinKapt3Test.FILE_SEPARATOR)
|
.joinToString(AbstractKotlinKapt3Test.FILE_SEPARATOR)
|
||||||
|
|
||||||
super.saveStubs(stubs)
|
super.saveStubs(kaptContext, stubs)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun saveIncrementalData(
|
override fun saveIncrementalData(
|
||||||
|
|||||||
+6
-2
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.kapt3.doAnnotationProcessing
|
|||||||
import org.jetbrains.kotlin.kapt3.javac.KaptJavaFileObject
|
import org.jetbrains.kotlin.kapt3.javac.KaptJavaFileObject
|
||||||
import org.jetbrains.kotlin.kapt3.javac.KaptJavaLog
|
import org.jetbrains.kotlin.kapt3.javac.KaptJavaLog
|
||||||
import org.jetbrains.kotlin.kapt3.parseJavaFiles
|
import org.jetbrains.kotlin.kapt3.parseJavaFiles
|
||||||
|
import org.jetbrains.kotlin.kapt3.prettyPrint
|
||||||
import org.jetbrains.kotlin.kapt3.stubs.ClassFileToSourceStubConverter
|
import org.jetbrains.kotlin.kapt3.stubs.ClassFileToSourceStubConverter
|
||||||
import org.jetbrains.kotlin.kapt3.util.KaptLogger
|
import org.jetbrains.kotlin.kapt3.util.KaptLogger
|
||||||
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension
|
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension
|
||||||
@@ -116,7 +117,7 @@ abstract class AbstractKotlinKapt3Test : CodegenTestCase() {
|
|||||||
val converter = ClassFileToSourceStubConverter(kaptContext, generateNonExistentClass, correctErrorTypes)
|
val converter = ClassFileToSourceStubConverter(kaptContext, generateNonExistentClass, correctErrorTypes)
|
||||||
|
|
||||||
val convertedTrees = converter.convert()
|
val convertedTrees = converter.convert()
|
||||||
val convertedFiles = convertedTrees.map { tree -> createTempFile("stub", ".java", tree.toString()) }
|
val convertedFiles = convertedTrees.map { tree -> createTempFile("stub", ".java", tree.prettyPrint(kaptContext.context)) }
|
||||||
|
|
||||||
val allJavaFiles = javaFiles + convertedFiles
|
val allJavaFiles = javaFiles + convertedFiles
|
||||||
|
|
||||||
@@ -194,7 +195,10 @@ open class AbstractClassFileToSourceStubConverterTest : AbstractKotlinKapt3Test(
|
|||||||
kaptContext.javaLog.interceptorData.files = convertedFiles.map { it.sourceFile to it }.toMap()
|
kaptContext.javaLog.interceptorData.files = convertedFiles.map { it.sourceFile to it }.toMap()
|
||||||
if (validate) kaptContext.compiler.enterTrees(convertedFiles)
|
if (validate) kaptContext.compiler.enterTrees(convertedFiles)
|
||||||
|
|
||||||
val actualRaw = convertedFiles.sortedBy { it.sourceFile.name }.joinToString(FILE_SEPARATOR)
|
val actualRaw = convertedFiles
|
||||||
|
.sortedBy { it.sourceFile.name }
|
||||||
|
.joinToString(FILE_SEPARATOR) { it.prettyPrint(kaptContext.context) }
|
||||||
|
|
||||||
val actual = StringUtil.convertLineSeparators(actualRaw.trim({ it <= ' ' }))
|
val actual = StringUtil.convertLineSeparators(actualRaw.trim({ it <= ' ' }))
|
||||||
.trimTrailingWhitespacesAndAddNewlineAtEOF()
|
.trimTrailingWhitespacesAndAddNewlineAtEOF()
|
||||||
.let { removeMetadataAnnotationContents(it) }
|
.let { removeMetadataAnnotationContents(it) }
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 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.kapt3.test;
|
||||||
|
|
||||||
|
public enum Jclass {
|
||||||
|
BLACK, @Anno WHITE
|
||||||
|
}
|
||||||
|
|
||||||
|
@interface Anno {}
|
||||||
@@ -29,3 +29,7 @@ class TestAnno2 {
|
|||||||
@get:Anno3("getter") @set:Anno3("setter") @property:Anno3("property") @field:Anno3("field") @setparam:Anno3("setparam")
|
@get:Anno3("getter") @set:Anno3("setter") @property:Anno3("property") @field:Anno3("field") @setparam:Anno3("setparam")
|
||||||
var b: String = "property initializer"
|
var b: String = "property initializer"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class Enum1 {
|
||||||
|
BLACK, @Anno1 WHITE
|
||||||
|
}
|
||||||
@@ -69,6 +69,21 @@ public enum Colors {
|
|||||||
////////////////////
|
////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
@kotlin.Metadata()
|
||||||
|
@kapt.internal.KaptMetadata()
|
||||||
|
public enum Enum1 {
|
||||||
|
/*public static final*/ BLACK /* = new Enum1() */,
|
||||||
|
@Anno1()
|
||||||
|
/*public static final*/ WHITE /* = new Enum1() */;
|
||||||
|
|
||||||
|
@kapt.internal.KaptSignature(value = "<init>(Ljava/lang/String;I)V")
|
||||||
|
Enum1() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
|
||||||
|
|
||||||
@kotlin.Metadata()
|
@kotlin.Metadata()
|
||||||
@Anno3(value = "value")
|
@Anno3(value = "value")
|
||||||
@Anno2(a = @Anno1(), clazz = TestAnno.class, classes = {TestAnno.class, Anno1.class})
|
@Anno2(a = @Anno1(), clazz = TestAnno.class, classes = {TestAnno.class, Anno1.class})
|
||||||
|
|||||||
@@ -68,7 +68,9 @@ package test;
|
|||||||
@Anno(value = "enum")
|
@Anno(value = "enum")
|
||||||
@kapt.internal.KaptMetadata()
|
@kapt.internal.KaptMetadata()
|
||||||
public enum Enum {
|
public enum Enum {
|
||||||
|
@Anno(value = "white")
|
||||||
/*public static final*/ WHITE /* = new Enum() */,
|
/*public static final*/ WHITE /* = new Enum() */,
|
||||||
|
@Anno(value = "black")
|
||||||
/*public static final*/ BLACK /* = new Enum() */;
|
/*public static final*/ BLACK /* = new Enum() */;
|
||||||
private final int x = 0;
|
private final int x = 0;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user