Implement TurbineAnnotationItem
This CL aims to make the test `test annotations` pass for Turbine
Bug: 308386397
Test: ./gradlew
Change-Id: If0d2a3e1ac4804e936f3469baaf106207035a7d3
diff --git a/metalava-model-turbine/src/main/java/com/android/tools/metalava/model/turbine/TurbineAnnotationItem.kt b/metalava-model-turbine/src/main/java/com/android/tools/metalava/model/turbine/TurbineAnnotationItem.kt
new file mode 100644
index 0000000..365ae1f
--- /dev/null
+++ b/metalava-model-turbine/src/main/java/com/android/tools/metalava/model/turbine/TurbineAnnotationItem.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * 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 com.android.tools.metalava.model.turbine
+
+import com.android.tools.metalava.model.AnnotationAttribute
+import com.android.tools.metalava.model.DefaultAnnotationItem
+
+class TurbineAnnotationItem
+constructor(
+ override val codebase: TurbineBasedCodebase,
+ originalName: String?,
+ val annotationAttribute: List<AnnotationAttribute>,
+) : DefaultAnnotationItem(codebase, originalName, { annotationAttribute }) {}
diff --git a/metalava-model-turbine/src/main/java/com/android/tools/metalava/model/turbine/TurbineCodebaseInitialiser.kt b/metalava-model-turbine/src/main/java/com/android/tools/metalava/model/turbine/TurbineCodebaseInitialiser.kt
index 98b4cfe..a140600 100644
--- a/metalava-model-turbine/src/main/java/com/android/tools/metalava/model/turbine/TurbineCodebaseInitialiser.kt
+++ b/metalava-model-turbine/src/main/java/com/android/tools/metalava/model/turbine/TurbineCodebaseInitialiser.kt
@@ -16,6 +16,12 @@
package com.android.tools.metalava.model.turbine
+import com.android.tools.metalava.model.AnnotationAttribute
+import com.android.tools.metalava.model.AnnotationAttributeValue
+import com.android.tools.metalava.model.AnnotationItem
+import com.android.tools.metalava.model.DefaultAnnotationArrayAttributeValue
+import com.android.tools.metalava.model.DefaultAnnotationAttribute
+import com.android.tools.metalava.model.DefaultAnnotationSingleAttributeValue
import com.google.common.collect.ImmutableList
import com.google.common.collect.ImmutableMap
import com.google.turbine.binder.Binder
@@ -23,13 +29,19 @@
import com.google.turbine.binder.ClassPathBinder
import com.google.turbine.binder.Processing.ProcessorInfo
import com.google.turbine.binder.bound.SourceTypeBoundClass
+import com.google.turbine.binder.bound.TurbineClassValue
import com.google.turbine.binder.bound.TypeBoundClass
import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo
import com.google.turbine.binder.bytecode.BytecodeBoundClass
import com.google.turbine.binder.env.CompoundEnv
import com.google.turbine.binder.sym.ClassSymbol
import com.google.turbine.diag.TurbineLog
+import com.google.turbine.model.Const
+import com.google.turbine.model.Const.ArrayInitValue
+import com.google.turbine.model.Const.Kind
+import com.google.turbine.model.Const.Value
import com.google.turbine.tree.Tree.CompUnit
+import com.google.turbine.type.AnnoInfo
import java.io.File
import java.util.Optional
import javax.lang.model.SourceVersion
@@ -121,7 +133,7 @@
if (pkgItem != null) {
return pkgItem as TurbinePackageItem
} else {
- val modifers = TurbineModifierItem.create(codebase, 0)
+ val modifers = TurbineModifierItem.create(codebase, 0, null)
val turbinePkgItem = TurbinePackageItem.create(codebase, name, modifers)
codebase.addPackage(turbinePkgItem)
return turbinePkgItem
@@ -167,7 +179,8 @@
val qualifiedName = sym.binaryName().replace('/', '.').replace('$', '.')
val simpleName = qualifiedName.substring(qualifiedName.lastIndexOf('.') + 1)
val fullName = sym.simpleName().replace('$', '.')
- val modifierItem = TurbineModifierItem.create(codebase, cls.access())
+ val annotations = createAnnotations(cls.annotations()).toMutableList()
+ val modifierItem = TurbineModifierItem.create(codebase, cls.access(), annotations)
val classItem =
TurbineClassItem(
codebase,
@@ -222,7 +235,9 @@
private fun createFields(classItem: TurbineClassItem, fields: ImmutableList<FieldInfo>) {
classItem.fields =
fields.map { field ->
- val fieldModifierItem = TurbineModifierItem.create(codebase, field.access())
+ val annotations = createAnnotations(field.annotations()).toMutableList()
+ val fieldModifierItem =
+ TurbineModifierItem.create(codebase, field.access(), annotations)
TurbineFieldItem(
codebase,
field.name(),
@@ -231,4 +246,57 @@
)
}
}
+
+ /** Creates a list of AnnotationItems from given list of Turbine Annotations */
+ private fun createAnnotations(annotations: List<AnnoInfo>): List<AnnotationItem> {
+ return annotations.map { createAnnotation(it) }
+ }
+
+ private fun createAnnotation(annotation: AnnoInfo): TurbineAnnotationItem {
+ val annoAttrs = getAnnotationAttributes(annotation.values())
+ val nameList = annotation.tree().name().map { it.value() }
+ val simpleName = nameList.joinToString(separator = ".")
+ val clsSym = annotation.sym()
+ val qualifiedName =
+ if (clsSym == null) simpleName
+ else clsSym.binaryName().replace('/', '.').replace('$', '.')
+ return TurbineAnnotationItem(codebase, qualifiedName, annoAttrs)
+ }
+
+ /** Creates a list of AnnotationAttribute from the map of name-value attribute pairs */
+ private fun getAnnotationAttributes(
+ attrs: ImmutableMap<String, Const>
+ ): List<AnnotationAttribute> {
+ val attributes = mutableListOf<AnnotationAttribute>()
+ for ((name, value) in attrs) {
+ attributes.add(DefaultAnnotationAttribute(name, createAttrValue(value)))
+ }
+ return attributes
+ }
+
+ private fun createAttrValue(const: Const): AnnotationAttributeValue {
+ if (const.kind() == Kind.ARRAY) {
+ val arrayVal = const as ArrayInitValue
+ return DefaultAnnotationArrayAttributeValue(
+ { arrayVal.toString() },
+ { arrayVal.elements().map { createAttrValue(it) } }
+ )
+ }
+ return DefaultAnnotationSingleAttributeValue({ const.toString() }, { getValue(const) })
+ }
+
+ private fun getValue(const: Const): Any? {
+ when (const.kind()) {
+ Kind.PRIMITIVE -> {
+ val value = const as Value
+ return value.getValue()
+ }
+ // For cases like AnyClass.class, return the qualified name of AnyClass
+ Kind.CLASS_LITERAL -> {
+ val value = const as TurbineClassValue
+ return value.type().toString()
+ }
+ else -> return const.toString()
+ }
+ }
}
diff --git a/metalava-model-turbine/src/main/java/com/android/tools/metalava/model/turbine/TurbineModifierItem.kt b/metalava-model-turbine/src/main/java/com/android/tools/metalava/model/turbine/TurbineModifierItem.kt
index f4cdda8..880ed38 100644
--- a/metalava-model-turbine/src/main/java/com/android/tools/metalava/model/turbine/TurbineModifierItem.kt
+++ b/metalava-model-turbine/src/main/java/com/android/tools/metalava/model/turbine/TurbineModifierItem.kt
@@ -26,18 +26,22 @@
internal constructor(
codebase: Codebase,
flags: Int = PACKAGE_PRIVATE,
- annotations: MutableList<AnnotationItem>? = null,
-) : DefaultModifierList(codebase, flags, annotations), ModifierList, MutableModifierList {
+ annotations: List<AnnotationItem>?
+) :
+ DefaultModifierList(codebase, flags, annotations?.toMutableList()),
+ ModifierList,
+ MutableModifierList {
companion object {
fun create(
codebase: Codebase,
flag: Int,
+ annotations: List<AnnotationItem>?
): TurbineModifierItem {
if (flag == 0) {
// No Modifier. Default modifier is PACKAGE_PRIVATE in such case
- return TurbineModifierItem(codebase)
+ return TurbineModifierItem(codebase, annotations = annotations)
}
- return TurbineModifierItem(codebase, computeFlag(flag))
+ return TurbineModifierItem(codebase, computeFlag(flag), annotations)
}
/**
diff --git a/metalava-model-turbine/src/test/resources/model-test-suite-baseline.txt b/metalava-model-turbine/src/test/resources/model-test-suite-baseline.txt
index f8b0fd7..daca2a3 100644
--- a/metalava-model-turbine/src/test/resources/model-test-suite-baseline.txt
+++ b/metalava-model-turbine/src/test/resources/model-test-suite-baseline.txt
@@ -1,7 +1,6 @@
com.android.tools.metalava.model.testsuite.BootstrapSourceModelProviderTest
060 - check method exists[turbine,java]
070 - check constructor exists[turbine,java]
- 130 - test annotations[turbine,java]
com.android.tools.metalava.model.testsuite.CommonClassItemTest
Find method with type parameterized by two types[turbine,java]
@@ -12,14 +11,6 @@
MethodItem superMethods() on simple method[turbine,java]
MethodItem type[turbine,java]
-com.android.tools.metalava.model.testsuite.annotationitem.CommonAnnotationItemTest
- annotation with annotation values[turbine,java]
- annotation with boolean values[turbine,java]
- annotation with char values[turbine,java]
- annotation with class values[turbine,java]
- annotation with number values[turbine,java]
- annotation with string values[turbine,java]
-
com.android.tools.metalava.model.testsuite.typeitem.CommonTypeItemTest
Test class array types[turbine,java]
Test class types[turbine,java]