kapt: Support inherited annotations in Kotlin plugin
This commit is contained in:
+29
-6
@@ -33,7 +33,7 @@ import java.util.regex.Pattern
|
||||
import java.util.regex.PatternSyntaxException
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
public abstract class AnnotationCollectorExtensionBase() : ClassBuilderInterceptorExtension {
|
||||
public abstract class AnnotationCollectorExtensionBase(val supportInheritedAnnotations: Boolean) : ClassBuilderInterceptorExtension {
|
||||
|
||||
private object RecordTypes {
|
||||
val ANNOTATED_CLASS = "c"
|
||||
@@ -42,6 +42,8 @@ public abstract class AnnotationCollectorExtensionBase() : ClassBuilderIntercept
|
||||
|
||||
val SHORTENED_ANNOTATION = "a"
|
||||
val SHORTENED_PACKAGE_NAME = "p"
|
||||
|
||||
val CLASS_DECLARATION = "d"
|
||||
}
|
||||
|
||||
protected abstract val annotationFilterList: List<String>?
|
||||
@@ -126,8 +128,15 @@ public abstract class AnnotationCollectorExtensionBase() : ClassBuilderIntercept
|
||||
superName: String,
|
||||
interfaces: Array<out String>
|
||||
) {
|
||||
currentClassSimpleName = name.substringAfterLast('/')
|
||||
currentPackageName = name.substringBeforeLast('/', "").replace('/', '.')
|
||||
val currentClassSimpleName = name.substringAfterLast('/')
|
||||
val currentPackageName = name.substringBeforeLast('/', "").replace('/', '.')
|
||||
|
||||
this.currentClassSimpleName = currentClassSimpleName
|
||||
this.currentPackageName = currentPackageName
|
||||
|
||||
if (supportInheritedAnnotations) {
|
||||
recordClass(currentPackageName, currentClassSimpleName)
|
||||
}
|
||||
|
||||
super.defineClass(origin, version, access, name, signature, superName, interfaces)
|
||||
}
|
||||
@@ -170,6 +179,15 @@ public abstract class AnnotationCollectorExtensionBase() : ClassBuilderIntercept
|
||||
else !annotationFqName.startsWith("kotlin.jvm.internal.") //apply to all
|
||||
}
|
||||
|
||||
private fun recordClass(packageName: String, className: String) {
|
||||
val packageNameId = if (!packageName.isEmpty())
|
||||
shortenedPackageNameCache.save(packageName, writer)
|
||||
else null
|
||||
|
||||
val outputClassName = getOutputClassName(packageNameId, className)
|
||||
writer.write("${RecordTypes.CLASS_DECLARATION} $outputClassName\n")
|
||||
}
|
||||
|
||||
private fun recordAnnotation(name: String?, type: String, annotationDesc: String) {
|
||||
val annotationFqName = Type.getType(annotationDesc).getClassName()
|
||||
if (!isAnnotationHandled(annotationFqName)) return
|
||||
@@ -183,7 +201,7 @@ public abstract class AnnotationCollectorExtensionBase() : ClassBuilderIntercept
|
||||
else null
|
||||
|
||||
val className = this.currentClassSimpleName!!
|
||||
val outputClassName = if (packageNameId == null) className else "$packageNameId/$className"
|
||||
val outputClassName = getOutputClassName(packageNameId, className)
|
||||
val elementName = if (name != null) " $name" else ""
|
||||
|
||||
writer.write("$type $annotationId $outputClassName$elementName\n")
|
||||
@@ -193,6 +211,10 @@ public abstract class AnnotationCollectorExtensionBase() : ClassBuilderIntercept
|
||||
}
|
||||
}
|
||||
|
||||
private fun getOutputClassName(packageNameId: String?, className: String): String {
|
||||
return if (packageNameId == null) className else "$packageNameId/$className"
|
||||
}
|
||||
|
||||
private fun String.compilePatternOpt(): Pattern? {
|
||||
return try {
|
||||
Pattern.compile(this)
|
||||
@@ -220,8 +242,9 @@ public abstract class AnnotationCollectorExtensionBase() : ClassBuilderIntercept
|
||||
|
||||
public class AnnotationCollectorExtension(
|
||||
override val annotationFilterList: List<String>? = null,
|
||||
val outputFilename: String? = null
|
||||
) : AnnotationCollectorExtensionBase() {
|
||||
val outputFilename: String? = null,
|
||||
supportInheritedAnnotations: Boolean
|
||||
) : AnnotationCollectorExtensionBase(supportInheritedAnnotations) {
|
||||
|
||||
private var writerInternal: Writer? = null
|
||||
|
||||
|
||||
+13
-3
@@ -51,6 +51,8 @@ public object AnnotationCollectorConfigurationKeys {
|
||||
CompilerConfigurationKey.create<String>("annotation file name")
|
||||
public val STUBS_PATH: CompilerConfigurationKey<String> =
|
||||
CompilerConfigurationKey.create<String>("stubs output directory")
|
||||
public val INHERITED: CompilerConfigurationKey<String> =
|
||||
CompilerConfigurationKey.create<String>("support inherited annotations")
|
||||
}
|
||||
|
||||
public class AnnotationCollectorCommandLineProcessor : CommandLineProcessor {
|
||||
@@ -64,12 +66,17 @@ public class AnnotationCollectorCommandLineProcessor : CommandLineProcessor {
|
||||
CliOption("output", "<path>", "File in which annotated declarations will be placed", required = false)
|
||||
|
||||
public val STUBS_PATH_OPTION: CliOption =
|
||||
CliOption("stubs", "<path>", "Output path for stubs.", required = false)
|
||||
CliOption("stubs", "<path>", "Output path for stubs", required = false)
|
||||
|
||||
public val INHERITED_ANNOTATIONS_OPTION: CliOption =
|
||||
CliOption("inherited", "<true/false>",
|
||||
"True if collecting Kotlin class names for inherited annotations is needed", required = false)
|
||||
}
|
||||
|
||||
override val pluginId: String = ANNOTATION_COLLECTOR_COMPILER_PLUGIN_ID
|
||||
|
||||
override val pluginOptions: Collection<CliOption> = listOf(ANNOTATION_FILTER_LIST_OPTION, OUTPUT_FILENAME_OPTION, STUBS_PATH_OPTION)
|
||||
override val pluginOptions: Collection<CliOption> =
|
||||
listOf(ANNOTATION_FILTER_LIST_OPTION, OUTPUT_FILENAME_OPTION, STUBS_PATH_OPTION, INHERITED_ANNOTATIONS_OPTION)
|
||||
|
||||
override fun processOption(option: CliOption, value: String, configuration: CompilerConfiguration) {
|
||||
when (option) {
|
||||
@@ -79,6 +86,7 @@ public class AnnotationCollectorCommandLineProcessor : CommandLineProcessor {
|
||||
}
|
||||
OUTPUT_FILENAME_OPTION -> configuration.put(AnnotationCollectorConfigurationKeys.OUTPUT_FILENAME, value)
|
||||
STUBS_PATH_OPTION -> configuration.put(AnnotationCollectorConfigurationKeys.STUBS_PATH, value)
|
||||
INHERITED_ANNOTATIONS_OPTION -> configuration.put(AnnotationCollectorConfigurationKeys.INHERITED, value)
|
||||
else -> throw CliOptionProcessingException("Unknown option: ${option.name}")
|
||||
}
|
||||
}
|
||||
@@ -86,10 +94,12 @@ public class AnnotationCollectorCommandLineProcessor : CommandLineProcessor {
|
||||
|
||||
public class AnnotationCollectorComponentRegistrar : ComponentRegistrar {
|
||||
public override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
|
||||
val supportInheritedAnnotations = "true" == (configuration.get(AnnotationCollectorConfigurationKeys.INHERITED) ?: "true")
|
||||
|
||||
val annotationFilterList = configuration.get(AnnotationCollectorConfigurationKeys.ANNOTATION_FILTER_LIST)
|
||||
val outputFilename = configuration.get(AnnotationCollectorConfigurationKeys.OUTPUT_FILENAME)
|
||||
if (outputFilename != null) {
|
||||
val collectorExtension = AnnotationCollectorExtension(annotationFilterList, outputFilename)
|
||||
val collectorExtension = AnnotationCollectorExtension(annotationFilterList, outputFilename, supportInheritedAnnotations)
|
||||
ClassBuilderInterceptorExtension.registerExtension(project, collectorExtension)
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -55,7 +55,7 @@ public abstract class AbstractAnnotationProcessorBoxTest : CodegenTestCase() {
|
||||
val environment = KotlinCoreEnvironment.createForTests(getTestRootDisposable()!!, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
|
||||
val project = environment.project
|
||||
|
||||
val collectorExtension = AnnotationCollectorExtensionForTests()
|
||||
val collectorExtension = AnnotationCollectorExtensionForTests(false)
|
||||
ClassBuilderInterceptorExtension.registerExtension(project, collectorExtension)
|
||||
|
||||
myEnvironment = environment
|
||||
@@ -63,7 +63,9 @@ public abstract class AbstractAnnotationProcessorBoxTest : CodegenTestCase() {
|
||||
return collectorExtension
|
||||
}
|
||||
|
||||
private class AnnotationCollectorExtensionForTests : AnnotationCollectorExtensionBase() {
|
||||
private class AnnotationCollectorExtensionForTests(
|
||||
supportInheritedAnnotations: Boolean
|
||||
) : AnnotationCollectorExtensionBase(supportInheritedAnnotations) {
|
||||
val stringWriter = StringWriter()
|
||||
|
||||
override fun getWriter(diagnostic: DiagnosticSink) = stringWriter
|
||||
|
||||
Reference in New Issue
Block a user