1 /* <lambda>null2 * 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.cli.common 18 19 import com.android.SdkConstants 20 import com.android.tools.metalava.model.Codebase 21 import com.android.tools.metalava.model.api.surface.ApiVariantType 22 import com.android.tools.metalava.model.text.SignatureFile 23 import java.io.File 24 25 /** A previously released API. */ 26 sealed interface PreviouslyReleasedApi { 27 28 /** The last signature file, if any, defining the previously released API. */ 29 val lastSignatureFile: File? 30 31 /** Load the files into a list of [Codebase]s. */ 32 fun load(signatureFileLoader: (List<SignatureFile>) -> Codebase): Codebase 33 34 /** 35 * Combine this with [other] and return the result. 36 * 37 * This simply involves creating another [PreviouslyReleasedApi] that contains all the signature 38 * files from this plus all the signature files from [other]. 39 */ 40 fun combine(other: PreviouslyReleasedApi): PreviouslyReleasedApi 41 42 override fun toString(): String 43 44 companion object { 45 /** 46 * Create an optional [PreviouslyReleasedApi] instance from the list of [files] passed to 47 * the option [optionName]. 48 * 49 * If [files] is empty then this returns `null`. If [files] contains any `.jar` files then 50 * it is an error. Otherwise, this will assume all the files are signature files and return 51 * [SignatureBasedApi] that wraps a list of [SignatureFile]s. files. 52 */ 53 internal fun optionalPreviouslyReleasedApi( 54 optionName: String, 55 files: List<File>, 56 onlyUseLastForMainApiSurface: Boolean = true, 57 apiVariantType: ApiVariantType = ApiVariantType.CORE, 58 ): PreviouslyReleasedApi? = 59 if (files.isEmpty()) null 60 else { 61 // Extract the jar files, if any. 62 val jarFiles = files.filter { it.path.endsWith(SdkConstants.DOT_JAR) } 63 if (jarFiles.isNotEmpty()) 64 error( 65 "$optionName: Can no longer check compatibility against jar files like ${jarFiles.joinToString()} please use equivalent signature files" 66 ) 67 68 SignatureBasedApi.fromFiles( 69 files, 70 onlyUseLastForMainApiSurface, 71 apiVariantType, 72 ) 73 } 74 } 75 } 76 77 /** 78 * A previously released API defined by signature files. 79 * 80 * If a single file is provided then it may be a full API or a delta on another API. If multiple 81 * files are provided then they are expected to be provided in order from the narrowest API to the 82 * widest API, where all but the first files are deltas on the preceding file. 83 */ 84 data class SignatureBasedApi(val signatureFiles: List<SignatureFile>) : PreviouslyReleasedApi { 85 86 override val lastSignatureFile = signatureFiles.last().file 87 loadnull88 override fun load( 89 signatureFileLoader: (List<SignatureFile>) -> Codebase, 90 ) = signatureFileLoader(signatureFiles) 91 92 override fun combine(other: PreviouslyReleasedApi) = 93 SignatureBasedApi(signatureFiles + (other as SignatureBasedApi).signatureFiles) 94 95 override fun toString(): String { 96 return signatureFiles.joinToString(",") { it.file.path } 97 } 98 99 companion object { fromFilesnull100 fun fromFiles( 101 files: List<File>, 102 onlyUseLastForMainApiSurface: Boolean = true, 103 apiVariantType: ApiVariantType = ApiVariantType.CORE, 104 ): SignatureBasedApi { 105 val lastIndex = files.size - 1 106 return SignatureBasedApi( 107 SignatureFile.fromFiles( 108 files, 109 apiVariantTypeChooser = { apiVariantType }, 110 forMainApiSurfacePredicate = { index, _ -> 111 // The last file is assumed to be for the main API surface. 112 !onlyUseLastForMainApiSurface || index == lastIndex 113 }, 114 ) 115 ) 116 } 117 } 118 } 119