• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * 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
18 
19 import com.android.tools.lint.checks.infrastructure.TestFiles
20 import com.android.tools.metalava.cli.common.BaseCommandTest
21 import com.android.tools.metalava.cli.common.COMMON_BASELINE_OPTIONS_HELP
22 import com.android.tools.metalava.cli.common.CommonOptions
23 import com.android.tools.metalava.cli.common.ISSUE_REPORTING_OPTIONS_HELP
24 import com.android.tools.metalava.cli.common.SOURCE_OPTIONS_HELP
25 import com.android.tools.metalava.cli.compatibility.COMPATIBILITY_CHECK_OPTIONS_HELP
26 import com.android.tools.metalava.cli.lint.API_LINT_OPTIONS_HELP
27 import com.android.tools.metalava.cli.signature.SIGNATURE_FORMAT_OPTIONS_HELP
28 import com.android.tools.metalava.model.source.DEFAULT_JAVA_LANGUAGE_LEVEL
29 import com.android.tools.metalava.model.source.DEFAULT_KOTLIN_LANGUAGE_LEVEL
30 import com.android.tools.metalava.reporter.Issues
31 import java.io.File
32 import java.util.Locale
33 import kotlin.test.assertEquals
34 import org.junit.Assert
35 import org.junit.Test
36 
37 class MainCommandTest :
38     BaseCommandTest<MainCommand>({ executionEnvironment ->
39         MainCommand(
40             commonOptions = CommonOptions(),
41             executionEnvironment = executionEnvironment,
42         )
43     }) {
44 
45     private val EXPECTED_HELP =
46         """
47 Usage: metalava main [options] [flags]...
48 
49   The default sub-command that is run if no sub-command is specified.
50 
51 Options:
52   --api-class-resolution [api|api:classpath]
53                                              Determines how class resolution is performed when loading API signature
54                                              files. Any classes that cannot be found will be treated as empty.",
55 
56                                              api - will only look for classes in the API signature files.
57 
58                                              api:classpath (default) - will look for classes in the API signature files
59                                              first and then in the classpath.
60   --suppress-compatibility-meta-annotation <meta-annotation class>
61                                              Suppress compatibility checks for any elements within the scope of an
62                                              annotation which is itself annotated with the given meta-annotation.
63   --manifest <file>                          A manifest file, used to check permissions to cross check APIs and retrieve
64                                              min_sdk_version. (default: no manifest)
65   --hide-sdk-extensions-newer-than INT       Ignore SDK extensions version INT and above. Used to exclude finalized but
66                                              not yet released SDK extensions.
67   --typedefs-in-signatures [none|ref|inline]
68                                              Whether to include typedef annotations in signature files.
69 
70                                              none (default) - will not include typedef annotations in signature.
71 
72                                              ref - will include just a reference to the typedef class, which is not
73                                              itself part of the API and is not included as a class
74 
75                                              inline - will include the constants themselves into each usage site
76   -h, --help                                 Show this message and exit
77 
78 $SOURCE_OPTIONS_HELP
79 
80 $ISSUE_REPORTING_OPTIONS_HELP
81 
82 $COMMON_BASELINE_OPTIONS_HELP
83 
84 $GENERAL_REPORTING_OPTIONS_HELP
85 
86 $API_SELECTION_OPTIONS_HELP
87 
88 $API_LINT_OPTIONS_HELP
89 
90 $COMPATIBILITY_CHECK_OPTIONS_HELP
91 
92 Signature File Output:
93 
94   Options controlling the signature file output. The format of the generated file is determined by the options in the
95   `Signature Format Output` section.
96 
97   --api <file>                               Output file into which the API signature will be generated. If this is not
98                                              specified then no API signature file will be created.
99   --removed-api <file>                       Output file into which the API signatures for removed APIs will be
100                                              generated. If this is not specified then no removed API signature file will
101                                              be created.
102 
103 $SIGNATURE_FORMAT_OPTIONS_HELP
104 
105 $STUB_GENERATION_OPTIONS_HELP
106 
107 Arguments:
108   flags                                      See below.
109 
110 
111 API sources:
112 --source-files <files>
113                                              A comma separated list of source files to be parsed. Can also be @ followed
114                                              by a path to a text file containing paths to the full set of files to
115                                              parse.
116 --classpath <paths>
117                                              One or more directories or jars (separated by `:`) containing classes that
118                                              should be on the classpath when parsing the source files
119 --merge-qualifier-annotations <file>
120                                              An external annotations file to merge and overlay the sources, or a
121                                              directory of such files. Should be used for annotations intended for
122                                              inclusion in the API to be written out, e.g. nullability. Formats supported
123                                              are: IntelliJ's external annotations database format, .jar or .zip files
124                                              containing those, Android signature files, and Java stub files.
125 --merge-inclusion-annotations <file>
126                                              An external annotations file to merge and overlay the sources, or a
127                                              directory of such files. Should be used for annotations which determine
128                                              inclusion in the API to be written out, i.e. show and hide. The only format
129                                              supported is Java stub files.
130 --validate-nullability-from-merged-stubs
131                                              Triggers validation of nullability annotations for any class where
132                                              --merge-qualifier-annotations includes a Java stub file.
133 --validate-nullability-from-list
134                                              Triggers validation of nullability annotations for any class listed in the
135                                              named file (one top-level class per line, # prefix for comment line).
136 --nullability-warnings-txt <file>
137                                              Specifies where to write warnings encountered during validation of
138                                              nullability annotations. (Does not trigger validation by itself.)
139 --nullability-errors-non-fatal
140                                              Specifies that errors encountered during validation of nullability
141                                              annotations should not be treated as errors. They will be written out to
142                                              the file specified in --nullability-warnings-txt instead.
143 --hide-package <package>
144                                              Remove the given packages from the API even if they have not been marked
145                                              with @hide
146 --hide-annotation <annotation class>
147                                              Treat any elements annotated with the given annotation as hidden
148 --show-unannotated
149                                              Include un-annotated public APIs in the signature file as well
150 --java-source <level>
151                                              Sets the source level for Java source files; default is ${DEFAULT_JAVA_LANGUAGE_LEVEL}.
152 --kotlin-source <level>
153                                              Sets the source level for Kotlin source files; default is ${DEFAULT_KOTLIN_LANGUAGE_LEVEL}.
154 --sdk-home <dir>
155                                              If set, locate the `android.jar` file from the given Android SDK
156 --compile-sdk-version <api>
157                                              Use the given API level
158 --jdk-home <dir>
159                                              If set, add the Java APIs from the given JDK to the classpath
160 --stub-packages <package-list>
161                                              List of packages (separated by :) which will be used to filter out
162                                              irrelevant code. If specified, only code in these packages will be included
163                                              in signature files, stubs, etc. (This is not limited to just the stubs; the
164                                              name is historical.) You can also use ".*" at the end to match subpackages,
165                                              so `foo.*` will match both `foo` and `foo.bar`.
166 --subtract-api <api file>
167                                              Subtracts the API in the given signature or jar file from the current API
168                                              being emitted via --api, --stubs, --doc-stubs, etc. Note that the
169                                              subtraction only applies to classes; it does not subtract members.
170 --ignore-classes-on-classpath
171                                              Prevents references to classes on the classpath from being added to the
172                                              generated stub files.
173 --ignore-comments
174                                              Ignore any comments in source files.
175 
176 
177 Extracting Signature Files:
178 --dex-api <file>
179                                              Generate a DEX signature descriptor file listing the APIs
180 --proguard <file>
181                                              Write a ProGuard keep file for the API
182 --sdk-values <dir>
183                                              Write SDK values files to the given directory
184 
185 
186 Generating Stubs:
187 --doc-stubs <dir>
188                                              Generate documentation stub source files for the API. Documentation stub
189                                              files are similar to regular stub files, but there are some differences.
190                                              For example, in the stub files, we'll use special annotations like
191                                              @RecentlyNonNull instead of @NonNull to indicate that an element is
192                                              recently marked as non null, whereas in the documentation stubs we'll just
193                                              list this as @NonNull. Another difference is that @doconly elements are
194                                              included in documentation stubs, but not regular stubs, etc.
195 --kotlin-stubs
196                                              [CURRENTLY EXPERIMENTAL] If specified, stubs generated from Kotlin source
197                                              code will be written in Kotlin rather than the Java programming language.
198 --pass-through-annotation <annotation classes>
199                                              A comma separated list of fully qualified names of annotation classes that
200                                              must be passed through unchanged.
201 --exclude-annotation <annotation classes>
202                                              A comma separated list of fully qualified names of annotation classes that
203                                              must be stripped from metalava's outputs.
204 --enhance-documentation
205                                              Enhance documentation in various ways, for example auto-generating
206                                              documentation based on source annotations present in the code. This is
207                                              implied by --doc-stubs.
208 --exclude-documentation-from-stubs
209                                              Exclude element documentation (javadoc and kdoc) from the generated stubs.
210                                              (Copyright notices are not affected by this, they are always included.
211                                              Documentation stubs (--doc-stubs) are not affected.)
212 
213 
214 Diffs and Checks:
215 --migrate-nullness <api file>
216                                              Compare nullness information with the previous stable API and mark newly
217                                              annotated APIs as under migration.
218 
219 
220 Extracting Annotations:
221 --extract-annotations <zipfile>
222                                              Extracts source annotations from the source files and writes them into the
223                                              given zip file
224 --include-source-retention
225                                              If true, include source-retention annotations in the stub files. Does not
226                                              apply to signature files. Source retention annotations are extracted into
227                                              the external annotations files instead.
228 
229 
230 Injecting API Levels:
231 --apply-api-levels <api-versions.xml>
232                                              Reads an XML file containing API level descriptions and merges the
233                                              information into the documentation
234 
235 
236 Extracting API Levels:
237 --generate-api-levels <xmlfile>
238                                              Reads android.jar SDK files and generates an XML file recording the API
239                                              level for each class, method and field
240 --remove-missing-class-references-in-api-levels
241                                              Removes references to missing classes when generating the API levels XML
242                                              file. This can happen when generating the XML file for the non-updatable
243                                              portions of the module-lib sdk, as those non-updatable portions can
244                                              reference classes that are part of an updatable apex.
245 --android-jar-pattern <pattern>
246                                              Patterns to use to locate Android JAR files. The default is
247                                              ${"$"}ANDROID_HOME/platforms/android-%/android.jar.
248 --first-version
249                                              Sets the first API level to generate an API database from; usually 1
250 --current-version
251                                              Sets the current API level of the current source code
252 --current-codename
253                                              Sets the code name for the current source code
254 --current-jar
255                                              Points to the current API jar, if any
256 --sdk-extensions-root
257                                              Points to root of prebuilt extension SDK jars, if any. This directory is
258                                              expected to contain snapshots of historical extension SDK versions in the
259                                              form of stub jars. The paths should be on the format
260                                              "<int>/public/<module-name>.jar", where <int> corresponds to the extension
261                                              SDK version, and <module-name> to the name of the mainline module.
262 --sdk-extensions-info
263                                              Points to map of extension SDK APIs to include, if any. The file is a plain
264                                              text file and describes, per extension SDK, what APIs from that extension
265                                              to include in the file created via --generate-api-levels. The format of
266                                              each line is one of the following: "<module-name> <pattern> <ext-name>
267                                              [<ext-name> [...]]", where <module-name> is the name of the mainline module
268                                              this line refers to, <pattern> is a common Java name prefix of the APIs
269                                              this line refers to, and <ext-name> is a list of extension SDK names in
270                                              which these SDKs first appeared, or "<ext-name> <ext-id> <type>", where
271                                              <ext-name> is the name of an SDK, <ext-id> its numerical ID and <type> is
272                                              one of "platform" (the Android platform SDK), "platform-ext" (an extension
273                                              to the Android platform SDK), "standalone" (a separate SDK). Fields are
274                                              separated by whitespace. A mainline module may be listed multiple times.
275                                              The special pattern "*" refers to all APIs in the given mainline module.
276                                              Lines beginning with # are comments.
277 
278 
279 Generating API version history:
280 --generate-api-version-history <jsonfile>
281                                              Reads API signature files and generates a JSON file recording the API
282                                              version each class, method, and field was added in and (if applicable)
283                                              deprecated in. Required to generate API version JSON.
284 --api-version-signature-files <files>
285                                              An ordered list of text API signature files. The oldest API version should
286                                              be first, the newest last. This should not include a signature file for the
287                                              current API version, which will be parsed from the provided source files.
288                                              Not required to generate API version JSON if the current version is the
289                                              only version.
290 --api-version-names <strings>
291                                              An ordered list of strings with the names to use for the API versions from
292                                              --api-version-signature-files, and the name of the current API version.
293                                              Required to generate API version JSON.
294 
295 
296 Environment Variables:
297 METALAVA_DUMP_ARGV
298                                              Set to true to have metalava emit all the arguments it was invoked with.
299                                              Helpful when debugging or reproducing under a debugger what the build
300                                              system is doing.
301 METALAVA_PREPEND_ARGS
302                                              One or more arguments (concatenated by space) to insert into the command
303                                              line, before the documentation flags.
304 METALAVA_APPEND_ARGS
305                                              One or more arguments (concatenated by space) to append to the end of the
306                                              command line, after the generate documentation flags.
307         """
308             .trimIndent()
309 
310     @Test
Test helpnull311     fun `Test help`() {
312         commandTest {
313             args += listOf("main", "--help")
314             expectedStdout = EXPECTED_HELP
315         }
316     }
317 
318     @Test
Test invalid optionnull319     fun `Test invalid option`() {
320         commandTest {
321             args += listOf("main", "--blah-blah-blah")
322             expectedStderr =
323                 """
324 Aborting: Error: no such option: "--blah-blah-blah"
325 
326 $EXPECTED_HELP
327                 """
328                     .trimIndent()
329         }
330     }
331 
332     @Test
Test deprecated lowercase matching in issue configuration optionsnull333     fun `Test deprecated lowercase matching in issue configuration options`() {
334         // Temporarily set [options] as it is needed by the [ReporterOptions.reporter] when
335         // reporting [Issues.DEPRECATED_OPTION].
336         @Suppress("DEPRECATION")
337         options = Options()
338 
339         commandTest {
340             args +=
341                 listOf(
342                     "main",
343                     "--error",
344                     Issues.DEPRECATED_OPTION.name,
345                     "--hide",
346                     Issues.ADDED_FINAL.name.lowercase(Locale.US),
347                 )
348 
349             expectedStderr =
350                 """
351 error: Case-insensitive issue matching is deprecated, use --hide AddedFinal instead of --hide addedfinal [DeprecatedOption]
352                 """
353                     .trimIndent()
354 
355             verify { assertEquals(-1, exitCode, message = "exitCode") }
356         }
357     }
358 
359     @Test
Test for @filenull360     fun `Test for @file`() {
361         val dir = temporaryFolder.newFolder()
362         val files = (1..4).map { TestFiles.source("File$it.java", "File$it").createFile(dir) }
363         val fileList =
364             TestFiles.source(
365                 "files.lst",
366                 """
367             ${files[0]}
368             ${files[1]} ${files[2]}
369             ${files[3]}
370         """
371                     .trimIndent()
372             )
373 
374         val file = fileList.createFile(dir)
375 
376         commandTest {
377             args += listOf("main", "@$file")
378 
379             verify {
380                 fun normalize(f: File): String = f.relativeTo(dir).path
381                 Assert.assertEquals(
382                     files.map { normalize(it) },
383                     command.optionGroup.sources.map { normalize(it) }
384                 )
385             }
386         }
387     }
388 }
389