1 /*
2 * Copyright 2017 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 androidx.build.doclava
18
19 import org.gradle.api.tasks.Input
20 import org.gradle.api.tasks.InputFiles
21 import org.gradle.api.tasks.Optional
22 import org.gradle.api.tasks.OutputDirectory
23 import org.gradle.api.tasks.OutputFile
24 import org.gradle.api.tasks.javadoc.Javadoc
25 import org.gradle.external.javadoc.CoreJavadocOptions
26 import java.io.File
27
28 // external/doclava/src/com/google/doclava/Errors.java
29 val DEFAULT_DOCLAVA_CONFIG = ChecksConfig(
30 errors = listOf(
31 101, // unresolved link
32 103, // unknown tag
33 104 // unknown param name
34 ),
35 warnings = listOf(121 /* hidden type param */),
36 hidden = listOf(
37 111, // hidden super class
38 113 // @deprecation mismatch
39 )
40 )
41
addMultilineMultiValueOptionnull42 private fun <E> CoreJavadocOptions.addMultilineMultiValueOption(
43 name: String,
44 values: Collection<E>
45 ) {
46 addMultilineMultiValueOption(name).value = values.map { listOf(it.toString()) }
47 }
48
49 open class DoclavaTask : Javadoc() {
50
51 // All lowercase name to match MinimalJavadocOptions#docletpath
52 private var docletpath: List<File> = emptyList()
53
54 @Input
55 var checksConfig: ChecksConfig = DEFAULT_DOCLAVA_CONFIG
56
57 /**
58 * If non-null, the list of packages that will be treated as if they were
59 * marked with {@literal @hide}.<br>
60 * Packages names will be matched exactly; sub-packages are not automatically recognized.
61 */
62 @Optional
63 @Input
64 var hiddenPackages: Collection<String>? = null
65
66 /**
67 * If non-null and not-empty, the whitelist of packages that will be present in the generated
68 * stubs; if null or empty, then all packages have stubs generated.<br>
69 * Wildcards are accepted.
70 */
71 @Optional
72 @Input
73 var stubPackages: Set<String>? = null
74
75 @Input
76 var generateDocs = true
77
78 /**
79 * If non-null, the location of where to place the generated api file.
80 * If this is non-null, then {@link #removedApiFile} must be non-null as well.
81 */
82 @Optional
83 @OutputFile
84 var apiFile: File? = null
85
86 /**
87 * If non-null, the location of where to place the generated removed api file.
88 * If this is non-null, then {@link #apiFile} must be non-null as well.
89 */
90 @Optional
91 @OutputFile
92 var removedApiFile: File? = null
93
94 /**
95 * If non-null, the location of the generated keep list.
96 */
97 @Optional
98 @OutputFile
99 var keepListFile: File? = null
100
101 /**
102 * If non-null, the location to put the generated stub sources.
103 */
104 @Optional
105 @OutputDirectory
106 var stubsDir: File? = null
107
108 init {
109 setFailOnError(true)
110 options.doclet = "com.google.doclava.Doclava"
111 options.encoding("UTF-8")
112 options.quiet()
113 // doclava doesn't understand '-doctitle'
114 title = null
115 maxMemory = "1280m"
116 // If none of generateDocs, apiFile, keepListFile, or stubJarsDir are true, then there is
117 // no work to do.
<lambda>null118 onlyIf({ generateDocs || apiFile != null || keepListFile != null || stubsDir != null })
119 }
120
121 /**
122 * The doclet path which has the {@code com.gogole.doclava.Doclava} class.
123 * This option will override any doclet path set in this instance's
124 * {@link #options JavadocOptions}.
125 * @see MinimalJavadocOptions#getDocletpath()
126 */
127 @InputFiles
getDocletpathnull128 fun getDocletpath(): List<File> {
129 return docletpath
130 }
131
132 /**
133 * Sets the doclet path which has the {@code com.gogole.doclava.Doclava} class.
134 * This option will override any doclet path set in this instance's
135 * {@link #options JavadocOptions}.
136 * @see MinimalJavadocOptions#setDocletpath(java.util.List)
137 */
setDocletpathnull138 fun setDocletpath(docletpath: Collection<File>) {
139 this.docletpath = docletpath.toList()
140 // Go ahead and keep the docletpath in our JavadocOptions object in sync.
141 options.docletpath = docletpath.toList()
142 }
143
144 /**
145 * "Configures" this DoclavaTask with parameters that might not be at their final values
146 * until this task is run.
147 */
<lambda>null148 private fun configureDoclava() = (options as CoreJavadocOptions).apply {
149
150 docletpath = this@DoclavaTask.docletpath
151
152 // configure doclava error/warning/hide levels
153 addMultilineMultiValueOption("hide", checksConfig.hidden)
154 addMultilineMultiValueOption("warning", checksConfig.warnings)
155 addMultilineMultiValueOption("error", checksConfig.errors)
156
157 if (hiddenPackages != null) {
158 addMultilineMultiValueOption("hidePackage", hiddenPackages!!)
159 }
160
161 if (!generateDocs) {
162 addBooleanOption("nodocs", true)
163 }
164
165 // If requested, generate the API files.
166 if (apiFile != null) {
167 addFileOption("api", apiFile)
168 addFileOption("removedApi", removedApiFile)
169 }
170
171 // If requested, generate the keep list.
172 addFileOption("proguard", keepListFile)
173
174 // If requested, generate stubs.
175 if (stubsDir != null) {
176 addFileOption("stubs", stubsDir)
177 val stubs = stubPackages
178 if (stubs != null) {
179 addStringOption("stubpackages", stubs.joinToString(":"))
180 }
181 }
182 // Always treat this as an Android docs task.
183 addBooleanOption("android", true)
184 }
185
coreJavadocOptionsnull186 fun coreJavadocOptions(configure: CoreJavadocOptions.() -> Unit) =
187 (options as CoreJavadocOptions).configure()
188
189 override fun generate() {
190 configureDoclava()
191 super.generate()
192 }
193 }
194