1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.tools.metalava.model.snapshot 18 19 import com.android.tools.metalava.model.ArrayTypeItem 20 import com.android.tools.metalava.model.ClassItem 21 import com.android.tools.metalava.model.ClassTypeItem 22 import com.android.tools.metalava.model.Codebase 23 import com.android.tools.metalava.model.LambdaTypeItem 24 import com.android.tools.metalava.model.PrimitiveTypeItem 25 import com.android.tools.metalava.model.TypeItem 26 import com.android.tools.metalava.model.TypeModifiers 27 import com.android.tools.metalava.model.TypeParameterScope 28 import com.android.tools.metalava.model.TypeTransformer 29 import com.android.tools.metalava.model.VariableTypeItem 30 import com.android.tools.metalava.model.WildcardTypeItem 31 import com.android.tools.metalava.model.type.ContextNullability 32 import com.android.tools.metalava.model.type.DefaultArrayTypeItem 33 import com.android.tools.metalava.model.type.DefaultClassTypeItem 34 import com.android.tools.metalava.model.type.DefaultLambdaTypeItem 35 import com.android.tools.metalava.model.type.DefaultPrimitiveTypeItem 36 import com.android.tools.metalava.model.type.DefaultTypeItemFactory 37 import com.android.tools.metalava.model.type.DefaultTypeModifiers 38 import com.android.tools.metalava.model.type.DefaultVariableTypeItem 39 import com.android.tools.metalava.model.type.DefaultWildcardTypeItem 40 41 /** 42 * A [DefaultTypeItemFactory] whose underlying type is another model's [TypeItem] that this will 43 * snapshot. 44 * 45 * TODO: Optimize by reusing them where possible as they are immutable. 46 */ 47 internal class SnapshotTypeItemFactory( 48 private val codebase: Codebase, 49 typeParameterScope: TypeParameterScope = TypeParameterScope.empty, 50 ) : DefaultTypeItemFactory<TypeItem, SnapshotTypeItemFactory>(typeParameterScope), TypeTransformer { 51 52 /** Construct a [SnapshotTypeItemFactory] suitable for creating types within [classItem]. */ fromnull53 fun from(classItem: ClassItem?): SnapshotTypeItemFactory { 54 val scope = TypeParameterScope.from(classItem) 55 return if (scope.isEmpty()) this else SnapshotTypeItemFactory(codebase, scope) 56 } 57 selfnull58 override fun self() = this 59 60 override fun createNestedFactory(scope: TypeParameterScope) = 61 SnapshotTypeItemFactory(codebase, scope) 62 63 override fun getType( 64 underlyingType: TypeItem, 65 contextNullability: ContextNullability, 66 isVarArg: Boolean 67 ) = underlyingType.transform(this) 68 69 /** 70 * Take a snapshot of the [TypeModifiers]. 71 * 72 * Only the [TypeModifiers.annotations] is model and [Codebase] dependent. All the other parts 73 * are model independent with no connection to a specific [Codebase]. So, this is reused as is 74 * if there are no [TypeModifiers.annotations]. 75 */ 76 private fun TypeModifiers.snapshot() = 77 if (annotations.isEmpty()) { 78 this 79 } else { 80 DefaultTypeModifiers( <lambda>null81 annotations.map { it.snapshot(codebase) }, 82 nullability, 83 ) 84 } 85 transformnull86 override fun transform(typeItem: ArrayTypeItem) = 87 DefaultArrayTypeItem( 88 typeItem.modifiers.snapshot(), 89 typeItem.componentType.transform(this), 90 typeItem.isVarargs, 91 ) 92 93 override fun transform(typeItem: ClassTypeItem) = 94 DefaultClassTypeItem( 95 codebase, 96 typeItem.modifiers.snapshot(), 97 typeItem.qualifiedName, 98 typeItem.arguments.map { it.transform(this) }, 99 typeItem.outerClassType?.transform(this), 100 ) 101 transformnull102 override fun transform(typeItem: LambdaTypeItem) = 103 DefaultLambdaTypeItem( 104 codebase, 105 typeItem.modifiers.snapshot(), 106 typeItem.qualifiedName, 107 typeItem.arguments.map { it.transform(this) }, 108 typeItem.outerClassType?.transform(this), 109 typeItem.isSuspend, 110 typeItem.receiverType?.transform(this), <lambda>null111 typeItem.parameterTypes.map { it.transform(this) }, 112 typeItem.returnType.transform(this), 113 ) 114 transformnull115 override fun transform(typeItem: PrimitiveTypeItem) = 116 DefaultPrimitiveTypeItem(typeItem.modifiers.snapshot(), typeItem.kind) 117 118 override fun transform(typeItem: VariableTypeItem) = 119 DefaultVariableTypeItem( 120 typeItem.modifiers.snapshot(), 121 typeParameterScope.getTypeParameter(typeItem.name), 122 ) 123 124 override fun transform(typeItem: WildcardTypeItem) = 125 DefaultWildcardTypeItem( 126 typeItem.modifiers.snapshot(), 127 typeItem.extendsBound?.transform(this), 128 typeItem.superBound?.transform(this), 129 ) 130 } 131