• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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