Extract common code for creating a List<TypeParameterItem>
Refactors the existing Turbine code into two separate parts. A generic
common method for use by all models that is parameterized by the model
specific types that represent parameters and their bounds.
This might not seem like much of an improvement on its own but it is
a step towards deduping model specific implementations of
`TypeParameterItem` and `TypeParameterList`.
Bug: 324196754
Test: ./gradlew
Change-Id: Id241488407f3e138682d03afc6d9fd97e06589d2
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 755a96c..e916fd2 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
@@ -29,6 +29,7 @@
import com.android.tools.metalava.model.DefaultAnnotationArrayAttributeValue
import com.android.tools.metalava.model.DefaultAnnotationAttribute
import com.android.tools.metalava.model.DefaultAnnotationSingleAttributeValue
+import com.android.tools.metalava.model.DefaultTypeParameterList
import com.android.tools.metalava.model.Item
import com.android.tools.metalava.model.MethodItem
import com.android.tools.metalava.model.PrimitiveTypeItem.Primitive
@@ -698,22 +699,16 @@
): TypeParameterList {
if (tyParams.isEmpty()) return TypeParameterList.NONE
+ // Create a list of [TypeParameterItem]s from turbine specific classes.
+ val typeParameters =
+ DefaultTypeParameterList.createListOfTypeParameterItems(
+ tyParams,
+ { sym, tyParam -> createTypeParameter(sym, tyParam) },
+ { item, bounds -> createTypeParameterBounds(bounds).also { item.bounds = it } },
+ )
+
val tyParamList = TurbineTypeParameterList(codebase)
-
- // Create and register all the TypeParameterItems in the list without bounds and group them
- // together with the corresponding TyVarInfo from which the bounds will be constructed.
- // This needs to be done separately to creating the type bounds as the type bounds can form
- // cycles within and between type parameters in a list.
- val paramAndTyParam =
- tyParams.map { (sym, tyParam) -> createTypeParameter(sym, tyParam) to tyParam }.toMap()
-
- // Now, update each TypeParameterItem with their bounds.
- for ((typeParamItem, tyParam) in paramAndTyParam) {
- typeParamItem.bounds = createTypeParameterBounds(tyParam)
- }
-
- // Finally, store the parameter list.
- tyParamList.typeParameters = paramAndTyParam.keys.toList()
+ tyParamList.typeParameters = typeParameters
return tyParamList
}
diff --git a/metalava-model-turbine/src/main/java/com/android/tools/metalava/model/turbine/TurbineTypeParameterList.kt b/metalava-model-turbine/src/main/java/com/android/tools/metalava/model/turbine/TurbineTypeParameterList.kt
index 07fc524..35da5ee 100644
--- a/metalava-model-turbine/src/main/java/com/android/tools/metalava/model/turbine/TurbineTypeParameterList.kt
+++ b/metalava-model-turbine/src/main/java/com/android/tools/metalava/model/turbine/TurbineTypeParameterList.kt
@@ -18,12 +18,13 @@
import com.android.tools.metalava.model.Codebase
import com.android.tools.metalava.model.DefaultTypeParameterList
+import com.android.tools.metalava.model.TypeParameterItem
internal class TurbineTypeParameterList(
val codebase: Codebase,
) : DefaultTypeParameterList() {
- internal lateinit var typeParameters: List<TurbineTypeParameterItem>
+ internal lateinit var typeParameters: List<TypeParameterItem>
- override fun typeParameters(): List<TurbineTypeParameterItem> = typeParameters
+ override fun typeParameters(): List<TypeParameterItem> = typeParameters
}
diff --git a/metalava-model/src/main/java/com/android/tools/metalava/model/TypeParameterList.kt b/metalava-model/src/main/java/com/android/tools/metalava/model/TypeParameterList.kt
index 539146c..4aed2fd 100644
--- a/metalava-model/src/main/java/com/android/tools/metalava/model/TypeParameterList.kt
+++ b/metalava-model/src/main/java/com/android/tools/metalava/model/TypeParameterList.kt
@@ -68,4 +68,40 @@
override fun toString(): String {
return toString
}
+
+ companion object {
+ /**
+ * Create a [TypeParameterList] from model specific parameter and bounds information.
+ *
+ * @param inputParams a map from the model specific parameter [P] to the corresponding model
+ * specific bounds [B].
+ * @param paramFactory a function that will create a [TypeParameterItem] from the model
+ * specified parameter [P] and then register, so it can be found by [boundsFactory].
+ * @param boundsSetter a function that will create a list of [BoundTypeItem] from the model
+ * specific bounds and store it in [TypeParameterItem.typeBounds].
+ * @param P the model specific type parameter type.
+ * @param B the model specific bounds type.
+ */
+ fun <I : TypeParameterItem, P, B> createListOfTypeParameterItems(
+ inputParams: Map<P, B>,
+ paramFactory: (P, B) -> I,
+ boundsSetter: (I, B) -> List<BoundsTypeItem>,
+ ): List<TypeParameterItem> {
+
+ // First, create a Map from [TypeParameterItem] to model specific bounds. Using the
+ // [paramFactory] to convert the model specific parameter to a [TypeParameterItem].
+ val typeParameterItemToBounds =
+ inputParams.map { (param, bounds) -> paramFactory(param, bounds) to bounds }.toMap()
+
+ // Secondly, create and set the bounds in the [TypeParameterItem].
+ for ((typeParameter, bounds) in typeParameterItemToBounds) {
+ val boundsTypeItem = boundsSetter(typeParameter, bounds)
+ if (typeParameter.typeBounds() !== boundsTypeItem)
+ error("boundsSetter did not set bounds")
+ }
+
+ // Create a List<TypeParameterItem> from the keys.
+ return typeParameterItemToBounds.keys.toList()
+ }
+ }
}