1/* 2 * Copyright (C) 2016 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 17package android.support.doclava; 18 19import org.gradle.api.InvalidUserDataException 20import org.gradle.api.Nullable 21import org.gradle.api.tasks.Input 22import org.gradle.api.tasks.InputFiles 23import org.gradle.api.tasks.javadoc.Javadoc 24import org.gradle.api.tasks.Optional 25import org.gradle.api.tasks.OutputDirectory 26import org.gradle.api.tasks.OutputFile 27import org.gradle.api.tasks.ParallelizableTask 28 29@ParallelizableTask 30public class DoclavaTask extends Javadoc { 31 32 // external/doclava/src/com/google/doclava/Errors.java 33 public static final def DEFAULT_DOCLAVA_ERRORS = Collections.unmodifiableSet([ 34 101, // unresolved link 35 103, // unknown tag 36 104, // unknown param name 37 ] as Set) 38 39 public static final def DEFAULT_DOCLAVA_WARNINGS = Collections.unmodifiableSet([ 40 121, // hidden type param 41 ] as Set) 42 43 44 public static final def DEFAULT_DOCLAVA_HIDDEN = Collections.unmodifiableSet([ 45 111, // hidden super class 46 113, // @deprecation mismatch 47 ] as Set) 48 49 50 // All lowercase name to match MinimalJavadocOptions#docletpath 51 private Collection<File> mDocletpath 52 53 // doclava error types which will cause the build to fail 54 @Input 55 Collection doclavaErrors = DEFAULT_DOCLAVA_ERRORS 56 @Input 57 Collection doclavaWarnings = DEFAULT_DOCLAVA_WARNINGS 58 // spammy doclava warnings which we want to hide 59 @Input 60 Collection doclavaHidden = DEFAULT_DOCLAVA_HIDDEN 61 62 /** 63 * If non-null, the list of packages that will be treated as if they were 64 * marked with {@literal @hide}.<br> 65 * Packages names will be matched exactly; sub-packages are not automatically recognized. 66 */ 67 @Optional 68 @Nullable 69 @Input 70 Collection hiddenPackages = null 71 72 /** 73 * If non-null and not-empty, the whitelist of packages that will be present in the generated 74 * stubs; if null or empty, then all packages have stubs generated.<br> 75 * Wildcards are accepted. 76 */ 77 @Optional 78 @Nullable 79 @Input 80 Set<String> stubPackages = null 81 82 @Input 83 boolean generateDocs = true 84 85 /** 86 * If non-null, the location of where to place the generated api file. 87 * If this is non-null, then {@link #removedApiFile} must be non-null as well. 88 */ 89 @Optional 90 @Nullable 91 @OutputFile 92 File apiFile = null 93 94 /** 95 * If non-null, the location of where to place the generated removed api file. 96 * If this is non-null, then {@link #apiFile} must be non-null as well. 97 */ 98 @Optional 99 @Nullable 100 @OutputFile 101 File removedApiFile = null 102 103 /** 104 * If non-null, the location of the generated keep list. 105 */ 106 @Optional 107 @Nullable 108 @OutputFile 109 File keepListFile = null 110 111 /** 112 * If non-null, the location to put the generated stub sources. 113 */ 114 @Optional 115 @Nullable 116 @OutputDirectory 117 File stubsDir = null 118 119 public DoclavaTask() { 120 failOnError = true 121 options.doclet = "com.google.doclava.Doclava" 122 options.encoding("UTF-8") 123 options.quiet() 124 // doclava doesn't understand '-doctitle' 125 title = null 126 maxMemory = "1280m" 127 // TODO(csyoung) Some way to override this? 128 // If none of generateDocs, apiFile, keepListFile, or stubJarsDir are true, then there is no work to do. 129 onlyIf( { getGenerateDocs() || 130 (getApiFile() != null && getRemovedApiFile() != null) || 131 getKeepListFile() != null || 132 getStubsDir() != null } ) 133 } 134 135 /** 136 * The doclet path which has the {@code com.gogole.doclava.Doclava} class. 137 * This option will override any doclet path set in this instance's {@link #options JavadocOptions}. 138 * @see MinimalJavadocOptions#getDocletpath() 139 */ 140 @InputFiles 141 public Collection<File> getDocletpath() { 142 return mDocletpath 143 } 144 145 /** 146 * Sets the doclet path which has the {@code com.gogole.doclava.Doclava} class. 147 * This option will override any doclet path set in this instance's {@link #options JavadocOptions}. 148 * @see MinimalJavadocOptions#setDocletpath(java.util.List) 149 */ 150 public void setDocletpath(Collection<File> docletpath) { 151 mDocletpath = docletpath 152 // Go ahead and keep the docletpath in our JavadocOptions object in sync. 153 options.docletpath = docletpath as List 154 } 155 156 public void setDoclavaErrors(Collection errors) { 157 // Make it serializable. 158 doclavaErrors = errors as int[] 159 } 160 161 public void setDoclavaWarnings(Collection warnings) { 162 // Make it serializable. 163 doclavaWarnings = warnings as int[] 164 } 165 166 public void setDoclavaHidden(Collection hidden) { 167 // Make it serializable. 168 doclavaHidden = hidden as int[] 169 } 170 171 private static boolean verifyAndGetGenerateApiFiles(File apiFile, File removedApiFile) { 172 if (apiFile == null) { 173 if (removedApiFile == null) { 174 return false 175 } else { 176 throw new InvalidUserDataException('removedApiFile specified but not apiFile') 177 } 178 } else { 179 return true 180 } 181 } 182 183 /** 184 * "Configures" this DoclavaTask with parameters that might not be at their final values 185 * until this task is run. 186 */ 187 private configureDoclava() { 188 options.docletpath = getDocletpath() as List 189 // configure doclava error/warning/hide levels 190 options.addOption(new DoclavaMultilineJavadocOptionFileOption('hide')) 191 .setValue(getDoclavaHidden().collect({[it.toString()]})) 192 options.addOption(new DoclavaMultilineJavadocOptionFileOption('warning')) 193 .setValue(getDoclavaWarnings().collect({[it.toString()]})) 194 options.addOption(new DoclavaMultilineJavadocOptionFileOption('error')) 195 .setValue(getDoclavaErrors().collect({[it.toString()]})) 196 197 Collection hiddenPackages = getHiddenPackages() 198 if (hiddenPackages) { 199 options.addOption(new DoclavaMultilineJavadocOptionFileOption('hidePackage')) 200 .setValue(hiddenPackages.collect({[it.toString()]})) 201 } 202 203 if (!getGenerateDocs()) { 204 options.addOption(new DoclavaJavadocOptionFileOption('nodocs')) 205 } 206 // If requested, generate the api files. 207 File apiFile = getApiFile() 208 File removedApiFile = getRemovedApiFile() 209 if (verifyAndGetGenerateApiFiles(apiFile, removedApiFile)) { 210 options.addStringOption('api', apiFile.absolutePath) 211 options.addStringOption('removedApi', removedApiFile.absolutePath) 212 } 213 // If requested, generate the keep list. 214 File keepListFile = getKeepListFile() 215 if (keepListFile != null) { 216 options.addStringOption('proguard', keepListFile.absolutePath) 217 } 218 // If requested, generate stubs. 219 File stubsDir = getStubsDir() 220 if (stubsDir != null) { 221 options.addStringOption('stubs', stubsDir.absolutePath) 222 Set<String> stubPackages = getStubPackages() 223 if (stubPackages) { 224 options.addStringOption('stubpackages', stubPackages.join(':')) 225 } 226 } 227 // Always treat this as an Android docs task. 228 options.addOption(new DoclavaJavadocOptionFileOption('android')) 229 } 230 231 @Override 232 public void generate() { 233 configureDoclava(); 234 super.generate(); 235 } 236}