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