From 6a786165082ccbbaef0587bf990ce5ce45db7ca2 Mon Sep 17 00:00:00 2001 From: Vincent Potucek Date: Sun, 5 Oct 2025 12:31:06 +0200 Subject: [PATCH] Add `error-prone.picnic.tech` --- gradle/libs.versions.toml | 4 +- ...ld.java-nullability-conventions.gradle.kts | 282 ++++++++++++++++-- .../PreInterruptThreadDumpPrinter.java | 2 +- .../options/TestDiscoveryOptionsMixin.java | 19 +- .../core/EngineExecutionOrchestrator.java | 4 +- 5 files changed, 276 insertions(+), 35 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 58974e90b9a9..973e404d81e6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -31,7 +31,9 @@ bndlib = { module = "biz.aQute.bnd:biz.aQute.bndlib", version.ref = "bnd" } checkstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkstyle" } classgraph = { module = "io.github.classgraph:classgraph", version = "4.8.181" } commons-io = { module = "commons-io:commons-io", version = "2.20.0" } -errorProne-core = { module = "com.google.errorprone:error_prone_core", version = "2.42.0" } +error-prone-core = { module = "com.google.errorprone:error_prone_core", version = "2.42.0" } +error-prone-contrib = { module = "tech.picnic.error-prone-support:error-prone-contrib", version = "0.25.0" } +refaster-runner = { module = "tech.picnic.error-prone-support:refaster-runner", version = "0.25.0" } fastcsv = { module = "de.siegmar:fastcsv", version = "4.0.0" } groovy = { module = "org.apache.groovy:groovy", version = "5.0.1" } groovy2-bom = { module = "org.codehaus.groovy:groovy-bom", version = "2.5.23" } diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts index 2bef782b14ed..accd445d47e7 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts @@ -1,6 +1,7 @@ import junitbuild.extensions.dependencyFromLibs import net.ltgt.gradle.errorprone.errorprone import net.ltgt.gradle.nullaway.nullaway +import java.lang.System.getenv plugins { `java-library` @@ -9,8 +10,10 @@ plugins { } dependencies { - errorprone(dependencyFromLibs("errorProne-core")) + errorprone(dependencyFromLibs("error-prone-contrib")) + errorprone(dependencyFromLibs("error-prone-core")) errorprone(dependencyFromLibs("nullaway")) + errorprone(dependencyFromLibs("refaster-runner")) constraints { errorprone("com.google.guava:guava") { version { @@ -27,29 +30,270 @@ nullaway { tasks.withType().configureEach { options.errorprone { + disableWarningsInGeneratedCode = true + errorproneArgs.add("-XepOpt:Refaster:NamePattern=^(?!.*Rules\\$).*") // might consider. + if (getenv("IN_PLACE").toBoolean()) { + errorproneArgs.addAll( + "-XepPatchLocation:IN_PLACE", // why only certain picnic rules apply? + "-XepPatchChecks:" + + "AddNullMarkedToPackageInfo," + + "AlwaysThrows," + + "AmbiguousJsonCreator," + + "AndroidInjectionBeforeSuper," + + "ArrayEquals," + + "ArrayFillIncompatibleType," + + "ArrayHashCode," + + "ArrayToString," + + "ArraysAsListPrimitiveArray," + + "AssertJNullnessAssertion," + + "AsyncCallableReturnsNull," + + "AsyncFunctionReturnsNull," + + "AutoValueBuilderDefaultsInConstructor," + + "AutoValueConstructorOrderChecker," + + "AutowiredConstructor," + + "BadAnnotationImplementation," + + "BadShiftAmount," + + "BanJNDI," + + "BoxedPrimitiveEquality," + + "BundleDeserializationCast," + + "CanonicalAnnotationSyntax," + + "CanonicalClassNameUsage," + + "ChainingConstructorIgnoresParameter," + + "CheckNotNullMultipleTimes," + + "CheckReturnValue," + + "ClassCastLambdaUsage," + + "CollectionIncompatibleType," + + "CollectionToArraySafeParameter," + + "CollectorMutability," + + "ComparableType," + + "ComparingThisWithNull," + + "ComparisonOutOfRange," + + "CompatibleWithAnnotationMisuse," + + "CompileTimeConstant," + + "ComputeIfAbsentAmbiguousReference," + + "ConditionalExpressionNumericPromotion," + + "ConstantNaming," + + "ConstantOverflow," + + "DaggerProvidesNull," + + "DangerousLiteralNull," + + "DeadException," + + "DeadThread," + + "DefaultCharset," + + "DereferenceWithNullBranch," + + "DiscardedPostfixExpression," + + "DoNotCall," + + "DoNotMock," + + "DoubleBraceInitialization," + + "DuplicateMapKeys," + + "DurationFrom," + + "DurationGetTemporalUnit," + + "DurationTemporalUnit," + + "DurationToLongTimeUnit," + + "EagerStringFormatting," + + "EmptyMethod," + + "EmptyMonoZip," + + "EqualsHashCode," + + "EqualsNaN," + + "EqualsNull," + + "EqualsReference," + + "EqualsWrongThing," + + "ExplicitArgumentEnumeration," + + "ExplicitEnumOrdering," + + "FloggerFormatString," + + "FloggerLogString," + + "FloggerLogVarargs," + + "FloggerSplitLogStatement," + + "FluxFlatMapUsage," + + "FluxImplicitBlock," + + "ForOverride," + + "FormatString," + + "FormatStringAnnotation," + + "FormatStringConcatenation," + + "FromTemporalAccessor," + + "FunctionalInterfaceMethodChanged," + + "FuturesGetCheckedIllegalExceptionType," + + "FuzzyEqualsShouldNotBeUsedInEqualsMethod," + + "GetClassOnAnnotation," + + "GetClassOnClass," + + "GuardedBy," + + "GuiceAssistedInjectScoping," + + "GuiceAssistedParameters," + + "GuiceInjectOnFinalField," + + "HashtableContains," + + "IdentityBinaryExpression," + + "IdentityConversion," + + "IdentityHashMapBoxing," + + "Immutable," + + "ImmutableEnumChecker," + + "ImmutablesSortedSetComparator," + + "ImpossibleNullComparison," + + "Incomparable," + + "IncompatibleArgumentType," + + "IncompatibleModifiers," + + "IndexOfChar," + + "InexactVarargsConditional," + + "InfiniteRecursion," + + "InjectMoreThanOneScopeAnnotationOnClass," + + "InjectOnMemberAndConstructor," + + "InlineMeValidator," + + "InstantTemporalUnit," + + "InvalidJavaTimeConstant," + + "InvalidPatternSyntax," + + "InvalidTimeZoneID," + + "InvalidZoneId," + + "IsInstanceIncompatibleType," + + "IsInstanceLambdaUsage," + + "IsInstanceOfClass," + + "IsLoggableTagLength," + + "JUnit3TestNotRun," + + "JUnit4ClassAnnotationNonStatic," + + "JUnit4SetUpNotRun," + + "JUnit4TearDownNotRun," + + "JUnit4TestNotRun," + + "JUnit4TestsNotRunWithinEnclosed," + + "JUnitAssertSameCheck," + + "JUnitClassModifiers," + + "JUnitMethodDeclaration," + + "JUnitNullaryParameterizedTestDeclaration," + + "JUnitParameterMethodNotFound," + + "JUnitValueSource," + + "JavaxInjectOnAbstractMethod," + + "JodaToSelf," + + "LenientFormatStringValidation," + + "LexicographicalAnnotationAttributeListing," + + "LexicographicalAnnotationListing," + + "LiteByteStringUtf8," + + "LocalDateTemporalAmount," + + "LockOnBoxedPrimitive," + + "LoopConditionChecker," + + "LossyPrimitiveCompare," + + "MathRoundIntLong," + + "MislabeledAndroidString," + + "MisleadingEmptyVarargs," + + "MisleadingEscapedSpace," + + "MisplacedScopeAnnotations," + + "MissingOverride," + + "MissingSuperCall," + + "MissingTestCall," + + "MisusedDayOfYear," + + "MisusedWeekYear," + + "MixedDescriptors," + + "MockitoMockClassReference," + + "MockitoStubbing," + + "MockitoUsage," + + "ModifyingCollectionWithItself," + + "MongoDBTextFilterUsage," + + "MoreThanOneInjectableConstructor," + + "MustBeClosedChecker," + + "NCopiesOfChar," + + "NestedOptionals," + + "NestedPublishers," + + "NoCanIgnoreReturnValueOnClasses," + + "NonCanonicalStaticImport," + + "NonEmptyMono," + + "NonFinalCompileTimeConstant," + + "NonRuntimeAnnotation," + + "NonStaticImport," + + "NullArgumentForNonNullParameter," + + "NullTernary," + + "NullableOnContainingClass," + + "OptionalEquality," + + "OptionalMapUnusedValue," + + "OptionalOfRedundantMethod," + + "OptionalOrElseGet," + + "OverlappingQualifierAndScopeAnnotation," + + "OverridesJavaxInjectableMethod," + + "PackageInfo," + + "ParametersButNotParameterized," + + "ParcelableCreator," + + "PeriodFrom," + + "PeriodGetTemporalUnit," + + "PeriodTimeMath," + + "PreconditionsInvalidPlaceholder," + + "PrimitiveComparison," + + "PrivateSecurityContractProtoAccess," + + "ProtoBuilderReturnValueIgnored," + + "ProtoStringFieldReferenceEquality," + + "ProtoTruthMixedDescriptors," + + "ProtocolBufferOrdinal," + + "ProvidesMethodOutsideOfModule," + + "RandomCast," + + "RandomModInteger," + + "RectIntersectReturnValueIgnored," + + "RedundantSetterCall," + + "RedundantStringConversion," + + "RedundantStringEscape," + + "RefasterAnyOfUsage," + + "RequestMappingAnnotation," + + "RequestParamType," + + "RequiredModifiers," + + "RestrictedApi," + + "ReturnValueIgnored," + + "SelfAssertion," + + "SelfAssignment," + + "SelfComparison," + + "SelfEquals," + + "SetUnrecognized," + + "ShouldHaveEvenArgs," + + "SizeGreaterThanOrEqualsZero," + + "Slf4jLogStatement," + + "Slf4jLoggerDeclaration," + + "SpringMvcAnnotation," + + "StaticImport," + + "StreamToString," + + "StringBuilderInitWithChar," + + "StringJoin," + + "StringJoin," + + "SubstringOfZero," + + "SuppressWarningsDeprecated," + + "TemporalAccessorGetChronoField," + + "TestParametersNotInitialized," + + "TheoryButNoTheories," + + "ThreadBuilderNameWithPlaceholder," + + "ThrowIfUncheckedKnownChecked," + + "ThrowNull," + + "TimeZoneUsage," + + "TreeToString," + + "TryFailThrowable," + + "TypeParameterQualifier," + + "UnicodeDirectionalityCharacters," + + "UnicodeInCode," + + "UnnecessaryCheckNotNull," + + "UnnecessaryTypeArgument," + + "UnsafeWildcard," + + "UnusedAnonymousClass," + + "UnusedCollectionModifiedInPlace," + + "VarTypeName," + + "WrongOneof," + + "XorPower," + + "ZoneIdOfZ," + ) + } val shouldDisableErrorProne = java.toolchain.implementation.orNull == JvmImplementation.J9 if (name == "compileJava" && !shouldDisableErrorProne) { disable( - - // This check is opinionated wrt. which method names it considers unsuitable for import which includes - // a few of our own methods in `ReflectionUtils` etc. - "BadImport", - - // The findings of this check are subjective because a named constant can be more readable in many cases - "UnnecessaryLambda", - - // Resolving findings for these checks requires ErrorProne's annotations which we don't want to use - "AnnotateFormatMethod", + // error-prone (https://errorprone.info/bugpatterns) + "AnnotateFormatMethod", // We don't want to use ErrorProne's annotations. + "BadImport", // This check is opinionated wrt. which method names it considers unsuitable for import which includes a few of our own methods in `ReflectionUtils` etc. + "DirectReturn", // https://github.com/junit-team/junit-framework/pull/5006#discussion_r2403984446 "DoNotCallSuggester", - "InlineMeSuggester", "ImmutableEnumChecker", - - // Resolving findings for this check requires using Guava which we don't want to use - "StringSplitter", - - // Produces a lot of findings that we consider to be false positives, for example for package-private - // classes and methods - "MissingSummary", + "InlineMeSuggester", + "MissingSummary", // Produces a lot of findings that we consider to be false positives, for example for package-private classes and methods. + "StringSplitter", // We don't want to use Guava. + "UnnecessaryLambda", // The findings of this check are subjective because a named constant can be more readable in many cases. + // error-prone.picnic (https://error-prone.picnic.tech) + "ConstantNaming", + "FormatStringConcatenation", + "IdentityConversion", + "LexicographicalAnnotationAttributeListing", + "LexicographicalAnnotationListing", + "NestedOptionals", + "NonStaticImport", + "OptionalOrElseGet", + "PrimitiveComparison", + "StaticImport", + "TimeZoneUsage", ) error("PackageLocation") } else { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/PreInterruptThreadDumpPrinter.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/PreInterruptThreadDumpPrinter.java index 283710eb1f1e..94147129d87b 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/PreInterruptThreadDumpPrinter.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/PreInterruptThreadDumpPrinter.java @@ -49,7 +49,7 @@ public void beforeThreadInterrupt(PreInterruptContext preInterruptContext, Exten sb.append(NL); // Use the same prefix as java.lang.Throwable.printStackTrace(PrintStreamOrWriter) sb.append("\tat "); - sb.append(stackTraceElement.toString()); + sb.append(stackTraceElement); } sb.append(NL); } diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptionsMixin.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptionsMixin.java index cce9455d8c98..37efc22027c3 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptionsMixin.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptionsMixin.java @@ -155,22 +155,18 @@ public static class FilterOptions { + "When this option is repeated, all patterns will be combined using OR semantics.") private final List excludeClassNamePatterns = new ArrayList<>(); - @Option(names = { - "--include-package" }, paramLabel = "PKG", arity = "1", description = "Provide a package to be included in the test run. This option can be repeated.") + @Option(names = "--include-package", paramLabel = "PKG", arity = "1", description = "Provide a package to be included in the test run. This option can be repeated.") private final List includePackages = new ArrayList<>(); - @Option(names = { - "--exclude-package" }, paramLabel = "PKG", arity = "1", description = "Provide a package to be excluded from the test run. This option can be repeated.") + @Option(names = "--exclude-package", paramLabel = "PKG", arity = "1", description = "Provide a package to be excluded from the test run. This option can be repeated.") private final List excludePackages = new ArrayList<>(); - @Option(names = { - "--include-methodname" }, paramLabel = "PATTERN", arity = "1", description = "Provide a regular expression to include only methods whose fully qualified names without parameters match. " // - + "When this option is repeated, all patterns will be combined using OR semantics.") + @Option(names = "--include-methodname", paramLabel = "PATTERN", arity = "1", description = "Provide a regular expression to include only methods whose fully qualified names without parameters match. " // + + "When this option is repeated, all patterns will be combined using OR semantics.") private final List includeMethodNamePatterns = new ArrayList<>(); - @Option(names = { - "--exclude-methodname" }, paramLabel = "PATTERN", arity = "1", description = "Provide a regular expression to exclude those methods whose fully qualified names without parameters match. " // - + "When this option is repeated, all patterns will be combined using OR semantics.") + @Option(names = "--exclude-methodname", paramLabel = "PATTERN", arity = "1", description = "Provide a regular expression to exclude those methods whose fully qualified names without parameters match. " // + + "When this option is repeated, all patterns will be combined using OR semantics.") private final List excludeMethodNamePatterns = new ArrayList<>(); @Option(names = { "-t", @@ -217,8 +213,7 @@ public static class RuntimeConfigurationOptions { // Implementation note: the @Option annotation is on a setter method to allow validation. private final Map configurationParameters = new LinkedHashMap<>(); - @Option(names = { - "--config-resource" }, paramLabel = "PATH", arity = "1", description = "Set configuration parameters for test discovery and execution via a classpath resource. This option can be repeated.") + @Option(names = "--config-resource", paramLabel = "PATH", arity = "1", description = "Set configuration parameters for test discovery and execution via a classpath resource. This option can be repeated.") private List configurationParametersResources = new ArrayList<>(); @CommandLine.Spec diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineExecutionOrchestrator.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineExecutionOrchestrator.java index 79c906e82a38..34db0d796685 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineExecutionOrchestrator.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineExecutionOrchestrator.java @@ -74,7 +74,7 @@ void execute(InternalTestPlan internalTestPlan, NamespacedHierarchicalStore requestLevelStore, CancellationToken cancellationToken) { @@ -166,7 +166,7 @@ private void withInterceptedStreams(ConfigurationParameters configurationParamet * discovery results} and notifies the supplied {@linkplain * EngineExecutionListener listener} of execution events. */ - @API(status = INTERNAL, since = "1.7", consumers = { "org.junit.platform.testkit" }) + @API(status = INTERNAL, since = "1.7", consumers = "org.junit.platform.testkit") public void execute(LauncherDiscoveryResult discoveryResult, EngineExecutionListener engineExecutionListener, NamespacedHierarchicalStore requestLevelStore, CancellationToken cancellationToken) { Preconditions.notNull(discoveryResult, "discoveryResult must not be null");