errorprone.py (10143B)
1 #!/usr/bin/env python3 2 # 3 # Copyright 2025 The Chromium Authors 4 # Use of this source code is governed by a BSD-style license that can be 5 # found in the LICENSE file. 6 """Run Error Prone.""" 7 8 import argparse 9 import sys 10 11 import compile_java 12 from util import server_utils 13 14 # Add a check here to cause the suggested fix to be applied while compiling. 15 # Use this when trying to enable more checks. 16 ERRORPRONE_CHECKS_TO_APPLY = [] 17 18 # Checks to disable in tests. 19 TESTONLY_ERRORPRONE_WARNINGS_TO_DISABLE = [ 20 # Too much effort to enable. 21 'UnusedVariable', 22 # These are allowed in tests. 23 'NoStreams', 24 ] 25 26 # Full list of checks: https://errorprone.info/bugpatterns 27 ERRORPRONE_WARNINGS_TO_DISABLE = [ 28 'InlineMeInliner', 29 'InlineMeSuggester', 30 # High priority to enable: 31 'HidingField', 32 'AlreadyChecked', 33 'DirectInvocationOnMock', 34 'MockNotUsedInProduction', 35 'PatternMatchingInstanceof', 36 'AssignmentExpression', 37 'RuleNotRun', 38 # High priority to enable in non-tests: 39 'JdkObsolete', 40 'ReturnValueIgnored', 41 'StaticAssignmentInConstructor', 42 # These are all for Javadoc, which we don't really care about. 43 # vvv 44 'InvalidBlockTag', 45 'InvalidParam', 46 'InvalidLink', 47 'InvalidInlineTag', 48 'MalformedInlineTag', 49 'MissingSummary', 50 'UnescapedEntity', 51 'UnrecognisedJavadocTag', 52 # ^^^ 53 'MutablePublicArray', 54 'NonCanonicalType', 55 'DoNotClaimAnnotations', 56 'JavaUtilDate', 57 'IdentityHashMapUsage', 58 'StaticMockMember', 59 # Triggers in tests where this is useful to do. 60 'StaticAssignmentOfThrowable', 61 # TODO(crbug.com/41384349): Follow steps in bug. 62 'CatchAndPrintStackTrace', 63 # TODO(crbug.com/41364806): Follow steps in bug. 64 'TypeParameterUnusedInFormals', 65 # Android platform default is always UTF-8. 66 # https://developer.android.com/reference/java/nio/charset/Charset.html#defaultCharset() 67 'DefaultCharset', 68 # There are lots of times when we just want to post a task. 69 'FutureReturnValueIgnored', 70 # Just false positives in our code. 71 'ThreadJoinLoop', 72 # Low priority corner cases with String.split. 73 # Linking Guava and using Splitter was rejected 74 # in the https://chromium-review.googlesource.com/c/chromium/src/+/871630. 75 'StringSplitter', 76 # Preferred to use another method since it propagates exceptions better. 77 'ClassNewInstance', 78 # Results in false positives. 79 'ThreadLocalUsage', 80 # Low priority. 81 'EqualsHashCode', 82 # Not necessary for tests. 83 'OverrideThrowableToString', 84 # Not that useful. 85 'UnsafeReflectiveConstructionCast', 86 # Not that useful. 87 'MixedMutabilityReturnType', 88 # Nice to have. 89 'EqualsGetClass', 90 # A lot of false-positives from CharSequence.equals(). 91 'UndefinedEquals', 92 # Dagger generated code triggers this. 93 'SameNameButDifferent', 94 # Does not apply to Android because it assumes no desugaring. 95 'UnnecessaryLambda', 96 # Nice to have. 97 'EmptyCatch', 98 # Nice to have. 99 'BadImport', 100 # Nice to have. 101 'UseCorrectAssertInTests', 102 # Must be off since we are now passing in annotation processor generated 103 # code as a source jar (deduplicating work with turbine). 104 'RefersToDaggerCodegen', 105 # We already have presubmit checks for this. We don't want it to fail 106 # local compiles. 107 'RemoveUnusedImports', 108 # Only has false positives (would not want to enable this). 109 'UnicodeEscape', 110 # A lot of existing violations. e.g. Should return List and not ArrayList 111 'NonApiType', 112 # Nice to have. 113 'StringCharset', 114 # Nice to have. 115 'StringConcatToTextBlock', 116 # Nice to have. 117 'StringCaseLocaleUsage', 118 # Low priority. 119 'RedundantControlFlow', 120 # Low priority. 121 'StatementSwitchToExpressionSwitch', 122 ] 123 124 # Full list of checks: https://errorprone.info/bugpatterns 125 # Only those marked as "experimental" need to be listed here in order to be 126 # enabled. 127 ERRORPRONE_WARNINGS_TO_ENABLE = [ 128 'BinderIdentityRestoredDangerously', 129 'EmptyIf', 130 'EqualsBrokenForNull', 131 'InvalidThrows', 132 'LongLiteralLowerCaseSuffix', 133 'MultiVariableDeclaration', 134 'RedundantOverride', 135 'StaticQualifiedUsingExpression', 136 'TimeUnitMismatch', 137 'UnnecessaryStaticImport', 138 'UseBinds', 139 'WildcardImport', 140 'NoStreams', 141 ] 142 143 144 def main(): 145 parser = argparse.ArgumentParser() 146 parser.add_argument('--skip-build-server', 147 action='store_true', 148 help='Avoid using the build server.') 149 parser.add_argument('--use-build-server', 150 action='store_true', 151 help='Always use the build server.') 152 parser.add_argument('--testonly', 153 action='store_true', 154 help='Disable some Error Prone checks') 155 parser.add_argument('--enable-nullaway', 156 action='store_true', 157 help='Enable NullAway (requires --enable-errorprone)') 158 parser.add_argument('--stamp', 159 required=True, 160 help='Path of output .stamp file') 161 options, compile_java_argv = parser.parse_known_args() 162 163 compile_java_argv += ['--jar-path', options.stamp] 164 165 # Use the build server for errorprone runs. 166 if not options.skip_build_server and (server_utils.MaybeRunCommand( 167 name=options.stamp, 168 argv=sys.argv, 169 stamp_file=options.stamp, 170 use_build_server=options.use_build_server)): 171 compile_java.main(compile_java_argv, write_depfile_only=True) 172 return 173 174 # All errorprone args are passed space-separated in a single arg. 175 errorprone_flags = ['-Xplugin:ErrorProne'] 176 177 if options.enable_nullaway: 178 # See: https://github.com/uber/NullAway/wiki/Configuration 179 # Check nullability only for classes marked with @NullMarked (this is our 180 # migration story). 181 errorprone_flags += ['-XepOpt:NullAway:OnlyNullMarked'] 182 errorprone_flags += [ 183 '-XepOpt:NullAway:CustomContractAnnotations=' 184 'org.chromium.build.annotations.Contract,' 185 'org.chromium.support_lib_boundary.util.Contract' 186 ] 187 # TODO(agrieve): Re-enable once this is fixed: 188 # https://github.com/uber/NullAway/issues/1104 189 # errorprone_flags += ['-XepOpt:NullAway:CheckContracts=true'] 190 191 # Make it a warning to use assumeNonNull() with a @NonNull. 192 errorprone_flags += [('-XepOpt:NullAway:CastToNonNullMethod=' 193 'org.chromium.build.NullUtil.assumeNonNull')] 194 # Detect "assert foo != null" as a null check. 195 errorprone_flags += ['-XepOpt:NullAway:AssertsEnabled=true'] 196 # Do not ignore @Nullable & @NonNull in non-@NullMarked classes. 197 errorprone_flags += [ 198 '-XepOpt:NullAway:AcknowledgeRestrictiveAnnotations=true' 199 ] 200 # Treat @RecentlyNullable the same as @Nullable. 201 errorprone_flags += ['-XepOpt:Nullaway:AcknowledgeAndroidRecent=true'] 202 # Enable experimental checking of @Nullable generics. 203 # https://github.com/uber/NullAway/wiki/JSpecify-Support 204 errorprone_flags += ['-XepOpt:NullAway:JSpecifyMode=true'] 205 # Treat these the same as constructors. 206 init_methods = [ 207 'android.app.Application.onCreate', 208 'android.app.Activity.onCreate', 209 'android.app.Service.onCreate', 210 'android.app.backup.BackupAgent.onCreate', 211 'android.content.ContentProvider.attachInfo', 212 'android.content.ContentProvider.onCreate', 213 'android.content.ContextWrapper.attachBaseContext', 214 'androidx.preference.PreferenceFragmentCompat.onCreatePreferences', 215 ] 216 errorprone_flags += [ 217 '-XepOpt:NullAway:KnownInitializers=' + ','.join(init_methods) 218 ] 219 220 # Make everything a warning so that when treat_warnings_as_errors is false, 221 # they do not fail the build. 222 errorprone_flags += ['-XepAllErrorsAsWarnings'] 223 # Don't check generated files (those tagged with @Generated). 224 errorprone_flags += ['-XepDisableWarningsInGeneratedCode'] 225 errorprone_flags.extend('-Xep:{}:OFF'.format(x) 226 for x in ERRORPRONE_WARNINGS_TO_DISABLE) 227 errorprone_flags.extend('-Xep:{}:WARN'.format(x) 228 for x in ERRORPRONE_WARNINGS_TO_ENABLE) 229 if options.testonly: 230 errorprone_flags.extend('-Xep:{}:OFF'.format(x) 231 for x in TESTONLY_ERRORPRONE_WARNINGS_TO_DISABLE) 232 233 if ERRORPRONE_CHECKS_TO_APPLY: 234 to_apply = list(ERRORPRONE_CHECKS_TO_APPLY) 235 if options.testonly: 236 to_apply = [ 237 x for x in to_apply 238 if x not in TESTONLY_ERRORPRONE_WARNINGS_TO_DISABLE 239 ] 240 errorprone_flags += [ 241 '-XepPatchLocation:IN_PLACE', '-XepPatchChecks:,' + ','.join(to_apply) 242 ] 243 244 # These are required to use JDK 16, and are taken directly from 245 # https://errorprone.info/docs/installation 246 javac_args = [ 247 '-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED', 248 '-J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED', 249 '-J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED', 250 '-J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED', 251 '-J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED', 252 '-J--add-exports=jdk.compiler/com.sun.tools.javac.processing=' 253 'ALL-UNNAMED', 254 '-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED', 255 '-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED', 256 '-J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED', 257 '-J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED', 258 ] 259 260 javac_args += ['-XDcompilePolicy=simple', ' '.join(errorprone_flags)] 261 262 javac_args += ['-XDshould-stop.ifError=FLOW'] 263 # This flag quits errorprone after checks and before code generation, since 264 # we do not need errorprone outputs, this speeds up errorprone by 4 seconds 265 # for chrome_java. 266 if not ERRORPRONE_CHECKS_TO_APPLY: 267 javac_args += ['-XDshould-stop.ifNoError=FLOW'] 268 269 compile_java.main(compile_java_argv, 270 extra_javac_args=javac_args, 271 use_errorprone=True) 272 273 274 if __name__ == '__main__': 275 main()