blob: 4ca5baef5384745f84c462c7a4bc65a66167256a [file] [log] [blame] [edit]
#!/usr/bin/env python3
#
# Copyright 2025 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Run Error Prone."""
import argparse
import sys
import compile_java
from util import server_utils
# Add a check here to cause the suggested fix to be applied while compiling.
# Use this when trying to enable more checks.
# BE SURE TO BUILD WITH --offline
ERRORPRONE_CHECKS_TO_APPLY = []
# Checks to disable in tests.
TESTONLY_ERRORPRONE_WARNINGS_TO_DISABLE = [
# Can hurt readability to enforce this on test classes.
'FieldCanBeStatic',
# These are allowed in tests.
'NoStreams',
# Too much effort to enable.
'UnusedVariable',
]
# Full list of checks: https://errorprone.info/bugpatterns
ERRORPRONE_WARNINGS_TO_DISABLE = [
'InlineMeInliner',
'InlineMeSuggester',
# High priority to enable:
'HidingField',
'AlreadyChecked',
'DirectInvocationOnMock',
'MockNotUsedInProduction',
'PatternMatchingInstanceof',
'AssignmentExpression',
'RuleNotRun',
# High priority to enable in non-tests:
'JdkObsolete',
'ReturnValueIgnored',
'StaticAssignmentInConstructor',
# These are all for Javadoc, which we don't really care about.
# vvv
'InvalidBlockTag',
'InvalidParam',
'InvalidLink',
'InvalidInlineTag',
'MalformedInlineTag',
'MissingSummary',
'NotJavadoc',
'UnescapedEntity',
'UnrecognisedJavadocTag',
# ^^^
'MutablePublicArray',
'NonCanonicalType',
'DoNotClaimAnnotations',
'JavaUtilDate',
'IdentityHashMapUsage',
'StaticMockMember',
# Triggers in tests where this is useful to do.
'StaticAssignmentOfThrowable',
# TODO(crbug.com/41384349): Follow steps in bug.
'CatchAndPrintStackTrace',
# TODO(crbug.com/41364806): Follow steps in bug.
'TypeParameterUnusedInFormals',
# Android platform default is always UTF-8.
# https://developer.android.com/reference/java/nio/charset/Charset.html#defaultCharset()
'DefaultCharset',
# There are lots of times when we just want to post a task.
'FutureReturnValueIgnored',
# Just false positives in our code.
'ThreadJoinLoop',
# Low priority corner cases with String.split.
# Linking Guava and using Splitter was rejected
# in the https://chromium-review.googlesource.com/c/chromium/src/+/871630.
'StringSplitter',
# Preferred to use another method since it propagates exceptions better.
'ClassNewInstance',
# Results in false positives.
'ThreadLocalUsage',
# Low priority.
'EqualsHashCode',
# Not necessary for tests.
'OverrideThrowableToString',
# Not that useful.
'UnsafeReflectiveConstructionCast',
# Not that useful.
'MixedMutabilityReturnType',
# Nice to have.
'EqualsGetClass',
# A lot of false-positives from CharSequence.equals().
'UndefinedEquals',
# Dagger generated code triggers this.
'SameNameButDifferent',
# Does not apply to Android because it assumes no desugaring.
'UnnecessaryLambda',
# Nice to have.
'EmptyCatch',
# Nice to have.
'BadImport',
# Nice to have.
'UseCorrectAssertInTests',
# Must be off since we are now passing in annotation processor generated
# code as a source jar (deduplicating work with turbine).
'RefersToDaggerCodegen',
# We already have presubmit checks for this. We don't want it to fail
# local compiles.
'RemoveUnusedImports',
# Only has false positives (would not want to enable this).
'UnicodeEscape',
# A lot of existing violations. e.g. Should return List and not ArrayList
'NonApiType',
# Nice to have.
'StringCharset',
# Nice to have.
'StringConcatToTextBlock',
# Nice to have.
'StringCaseLocaleUsage',
# Low priority.
'RedundantControlFlow',
# Low priority.
'StatementSwitchToExpressionSwitch',
# Assigning to fields marked as @Mock or @Spy. Suggested fix is to delete
# assignments, which would break tests in many cases.
'UnnecessaryAssignment',
# Serveral instances of using a string right before the String.format(),
# which seems better than inlining.
'InlineFormatString',
# Low priority.
'EffectivelyPrivate',
]
# Full list of checks: https://errorprone.info/bugpatterns
# Only those marked as "experimental" need to be listed here in order to be
# enabled.
ERRORPRONE_WARNINGS_TO_ENABLE = [
'BinderIdentityRestoredDangerously',
'EmptyIf',
'EqualsBrokenForNull',
'FieldCanBeFinal',
'FieldCanBeLocal',
'FieldCanBeStatic',
'InvalidThrows',
'LongLiteralLowerCaseSuffix',
'MultiVariableDeclaration',
'RedundantOverride',
'StaticQualifiedUsingExpression',
'TimeUnitMismatch',
'UnnecessaryStaticImport',
'UseBinds',
'WildcardImport',
'NoStreams',
]
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--use-build-server',
action='store_true',
help='Always use the build server.')
parser.add_argument('--testonly',
action='store_true',
help='Disable some Error Prone checks')
parser.add_argument('--enable-nullaway',
action='store_true',
help='Enable NullAway (requires --enable-errorprone)')
parser.add_argument('--stamp',
required=True,
help='Path of output .stamp file')
options, compile_java_argv = parser.parse_known_args()
compile_java_argv += ['--jar-path', options.stamp]
# Use the build server for errorprone runs.
if server_utils.MaybeRunCommand(
name=options.stamp,
argv=sys.argv,
stamp_file=options.stamp,
use_build_server=options.use_build_server):
compile_java.main(compile_java_argv, write_depfile_only=True)
return
# All errorprone args are passed space-separated in a single arg.
errorprone_flags = ['-Xplugin:ErrorProne']
if options.enable_nullaway:
# See: https://github.com/uber/NullAway/wiki/Configuration
# Check nullability only for classes marked with @NullMarked (this is our
# migration story).
errorprone_flags += ['-XepOpt:NullAway:OnlyNullMarked']
errorprone_flags += [
'-XepOpt:NullAway:CustomContractAnnotations='
'org.chromium.build.annotations.Contract,'
'org.chromium.support_lib_boundary.util.Contract'
]
# TODO(agrieve): Re-enable once this is fixed:
# https://github.com/uber/NullAway/issues/1104
# errorprone_flags += ['-XepOpt:NullAway:CheckContracts=true']
# Make it a warning to use assumeNonNull() with a @NonNull.
errorprone_flags += [('-XepOpt:NullAway:CastToNonNullMethod='
'org.chromium.build.NullUtil.assumeNonNull')]
# Detect "assert foo != null" as a null check.
errorprone_flags += ['-XepOpt:NullAway:AssertsEnabled=true']
# Do not ignore @Nullable & @NonNull in non-@NullMarked classes.
errorprone_flags += [
'-XepOpt:NullAway:AcknowledgeRestrictiveAnnotations=true'
]
# Treat @RecentlyNullable the same as @Nullable.
errorprone_flags += ['-XepOpt:Nullaway:AcknowledgeAndroidRecent=true']
# Enable experimental checking of @Nullable generics.
# https://github.com/uber/NullAway/wiki/JSpecify-Support
errorprone_flags += ['-XepOpt:NullAway:JSpecifyMode=true']
# Treat these the same as constructors.
# These are in addition to the default list in "DEFAULT_KNOWN_INITIALIZERS":
# https://github.com/uber/NullAway/blob/d5cb4f1190a96045d85b92c6d119e4595840cc8a/nullaway/src/main/java/com/uber/nullaway/ErrorProneCLIFlagsConfig.java#L128
init_methods = [
'android.app.backup.BackupAgent.onCreate',
'android.content.ContentProvider.attachInfo',
'android.content.ContentProvider.onCreate',
'android.content.ContextWrapper.attachBaseContext',
'androidx.preference.PreferenceFragmentCompat.onCreatePreferences',
]
errorprone_flags += [
'-XepOpt:NullAway:KnownInitializers=' + ','.join(init_methods)
]
# Make everything a warning so that when treat_warnings_as_errors is false,
# they do not fail the build.
errorprone_flags += ['-XepAllErrorsAsWarnings']
# Don't check generated files (those tagged with @Generated).
errorprone_flags += ['-XepDisableWarningsInGeneratedCode']
errorprone_flags.extend('-Xep:{}:OFF'.format(x)
for x in ERRORPRONE_WARNINGS_TO_DISABLE)
errorprone_flags.extend('-Xep:{}:WARN'.format(x)
for x in ERRORPRONE_WARNINGS_TO_ENABLE)
if options.testonly:
errorprone_flags.extend('-Xep:{}:OFF'.format(x)
for x in TESTONLY_ERRORPRONE_WARNINGS_TO_DISABLE)
if ERRORPRONE_CHECKS_TO_APPLY:
to_apply = list(ERRORPRONE_CHECKS_TO_APPLY)
if options.testonly:
to_apply = [
x for x in to_apply
if x not in TESTONLY_ERRORPRONE_WARNINGS_TO_DISABLE
]
errorprone_flags += [
'-XepPatchLocation:IN_PLACE', '-XepPatchChecks:,' + ','.join(to_apply)
]
# These are required to use JDK 16, and are taken directly from
# https://errorprone.info/docs/installation
javac_args = [
'-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED',
'-J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED',
'-J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED',
'-J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED',
'-J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED',
'-J--add-exports=jdk.compiler/com.sun.tools.javac.processing='
'ALL-UNNAMED',
'-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED',
'-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED',
'-J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED',
'-J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED',
]
javac_args += ['-XDcompilePolicy=simple', ' '.join(errorprone_flags)]
javac_args += ['-XDshould-stop.ifError=FLOW']
# This flag quits errorprone after checks and before code generation, since
# we do not need errorprone outputs, this speeds up errorprone by 4 seconds
# for chrome_java.
if not ERRORPRONE_CHECKS_TO_APPLY:
javac_args += ['-XDshould-stop.ifNoError=FLOW']
compile_java.main(compile_java_argv,
extra_javac_args=javac_args,
use_errorprone=True)
if __name__ == '__main__':
main()