• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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.signature
18 
19 import com.android.tools.metalava.OptionsDelegate
20 import com.android.tools.metalava.cli.common.MetalavaSubCommand
21 import com.android.tools.metalava.cli.common.cliError
22 import com.android.tools.metalava.cli.common.existingFile
23 import com.android.tools.metalava.cli.common.newFile
24 import com.android.tools.metalava.cli.common.progressTracker
25 import com.android.tools.metalava.createReportFile
26 import com.android.tools.metalava.model.text.ApiFile
27 import com.android.tools.metalava.model.text.ApiParseException
28 import com.android.tools.metalava.model.text.SignatureFile
29 import com.android.tools.metalava.model.text.SignatureWriter
30 import com.android.tools.metalava.model.text.createFilteringVisitorForSignatures
31 import com.android.tools.metalava.model.visitors.ApiPredicate
32 import com.android.tools.metalava.model.visitors.ApiType
33 import com.github.ajalt.clikt.parameters.arguments.argument
34 import com.github.ajalt.clikt.parameters.arguments.multiple
35 import com.github.ajalt.clikt.parameters.groups.provideDelegate
36 import com.github.ajalt.clikt.parameters.options.option
37 import com.github.ajalt.clikt.parameters.options.required
38 
39 class MergeSignaturesCommand :
40     MetalavaSubCommand(
41         help =
42             """
43                 Merge multiple signature files together into a single file.
44 
45                 The files must all be from the same API surface. The input files may overlap at the
46                 package and class level but if two files do include the same class they must be
47                 identical. Note: It is the user's responsibility to ensure that these constraints
48                 are met as metalava does not have the information available to enforce it. Failure
49                 to do so will result in undefined behavior.
50             """
51                 .trimIndent(),
52     ) {
53     /** Add options for controlling the format of the generated files. */
54     private val signatureFormat by SignatureFormatOptions()
55 
56     private val files by
57         argument(
58                 name = "<files>",
59                 help =
60                     """
61                         Multiple signature files that will be merged together.
62                     """
63                         .trimIndent()
64             )
65             .existingFile()
66             .multiple(required = true)
67 
68     private val out by
69         option(
70                 "--out",
71                 help =
72                     """
73                         The output file into which the result will be written. The format of the
74                         file will be determined by the options in `$SIGNATURE_FORMAT_OUTPUT_GROUP`.
75                     """
76                         .trimIndent()
77             )
78             .newFile()
79             .required()
80 
runnull81     override fun run() {
82         // Make sure that none of the code called by this command accesses the global `options`
83         // property.
84         OptionsDelegate.disallowAccess()
85 
86         try {
87             val codebase = ApiFile.parseApi(SignatureFile.fromFiles(files))
88             createReportFile(progressTracker, codebase, out, description = "Merged file") {
89                 val fileFormat = signatureFormat.fileFormat
90                 val signatureWriter =
91                     SignatureWriter(
92                         writer = it,
93                         fileFormat = fileFormat,
94                     )
95 
96                 createFilteringVisitorForSignatures(
97                     delegate = signatureWriter,
98                     fileFormat = fileFormat,
99                     apiType = ApiType.ALL,
100                     preFiltered = true,
101                     showUnannotated = false,
102                     apiPredicateConfig = ApiPredicate.Config(),
103                 )
104             }
105         } catch (e: ApiParseException) {
106             cliError(e.message)
107         }
108     }
109 }
110