Replace Checkstyle with Error Prone - #66
Open
ThoSap wants to merge 1 commit into
Open
Conversation
Member
Author
|
I a call I mentioned this to @SirCotare and he in favor of doing this, especially as it now it is less cumbersome for new contributors to start the project and we do not really love Checkstyle. I will also create a research task for Spotless and will open a RFC. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Checkstyle is removed from the build. Error Prone takes over the rules it enforced, and adds a large set it never had.
82 checks now run at ERROR, up from 2.
Every check was measured before it was enabled. No production logic changed.
See https://errorprone.info/bugpatterns for rule descriptions.
Why
It is cumbersome for new PR contributors to setup a GitHub Token just so they can download the AboutBits Java Checkstyle Config and compile the project.
I also saw in PR #60 that new contributors will easily get things wrong which could be prevented by something like Error Prone, for example the
Varifierrule I meantioned in the aforementioned PR.Error Prone was already wired in and running 54 checks at ERROR by default since the very start of the project.
Moving the rules there removes the blocker, removes a build tool, and removes the GitHub Packages credentials that only the Checkstyle config needed.
Also the Checkstyle upgrade was blocked.
Checkstyle 13.9.0 removed the
JavadocStylemodule, and the shared configit.aboutbits:java-checkstyle-configstill declares it in every published tag, RC2 through RC5.An unknown module name is a config load failure, not a violation, so the suppressions file cannot absorb it. Both
config/checkstyle/*.xmlfiles are regenerated from the artifact on every run, so the fix could not live in this repository.What the Checkstyle config actually enforced
The baseline is smaller than the module count suggests. RC5 declared 62 active modules:
checkstyle-suppressions-default.xmlcarries<suppress checks="Javadoc" files="."/>, a substring regex over every file.JavadocMethod,JavadocType,JavadocVariable,JavadocStyle,MissingJavadocMethodandInvalidJavadocPositionwere all off.IllegalInstantiationhas an emptyclassesproperty by default, so it reported nothing.MethodName,VisibilityModifier,FileTabCharacter,FileLength.Real baseline: 55 enforced rules on main sources.
Coverage
✅ Fully replaced (17)
AvoidStarImportWildcardImportUnusedImportsRemoveUnusedImportsParameterNumber(max 7)TooManyParameters, limit pinned to 7NeedBracesMissingBracesEqualsHashCodeEqualsHashCode(ERROR by default)InnerAssignmentAssignmentExpressionMissingSwitchDefaultMissingDefaultMultipleVariableDeclarationsMultiVariableDeclarationHideUtilityClassConstructorPrivateConstructorForUtilityClassInterfaceIsTypeInterfaceWithOnlyStaticsArrayTypeStyleMixedArrayDimensionsUpperEllLongLiteralLowerCaseSuffixJspecifyOnTopLevelTypes(custom)RequireExplicitNullMarking- exact same ruleInvalidJavadocPositionAnnotationPosition,NotJavadoc,AlmostJavadocJavadocMethodInvalidParam,InvalidThrows,InvalidLink,InvalidInlineTag,MalformedInlineTagJavadocTypeInvalidBlockTag,MissingSummaryJavadocStyleMissingSummary,EscapedEntity,UnescapedEntity,UnrecognisedJavadocTag🟡 Partially replaced (7)
ConstantNameConstantFieldstatic finalfor a CONSTANT_CASE name, but does not force a constant to be CONSTANT_CASERedundantModifierUnnecessaryFinalpublicon interface membersEmptyBlockEmptyCatch,EmptyIfSimplifyBooleanExpressionBooleanLiteral,ComplexBooleanConstantVisibilityModifierMutablePublicArray,ProtectedMembersInFinalClassJspecifyAnnotationOrder(custom)AnnotationPositionRoleReconcilerTestJspecifyInlineTypeUse(custom)AnnotationPosition❌ The 37 gaps
A. Layout - 16 modules, the one real loss
EmptyForIteratorPad,GenericWhitespace,MethodParamPad,NoWhitespaceAfter,NoWhitespaceBefore,OperatorWrap,ParenPad,TypecastParenPad,WhitespaceAfter,WhitespaceAround,LeftCurly,RightCurly,ModifierOrder,FileTabCharacter,NewlineAtEndOfFile,RegexpSingleline(trailing spaces).Error Prone matches on the javac AST and never sees the characters. The right owner is a formatter, which rewrites instead of reporting.
Follow-up: Spotless with google-java-format or palantir-java-format.
B. Naming - 8 modules, a deliberate decision
TypeName,MethodName,MemberName,LocalVariableName,LocalFinalVariableName,ParameterName,StaticVariableName,PackageName.IdentifierNamecovers all eight and is deliberately not enabled. It also enforces the Google acronym rule, so it demands 23 renames of public types and members:SQLUtil→SqlUtil,CRStatus→CrStatus,PostgreSQLContextFactory→PostgreSqlContextFactory,getDSLContext→getDslContext.That is a naming-policy change, not a tooling swap, and it belongs in its own PR.
C. Remaining 13, low value
MethodLength(max 150)FileLengthEmptyStatementUnnecessarySemicolonis the counterpart but stays off: Lombok makes it report every@Getterand@Setter, 1547 times over 39 positionsSimplifyBooleanReturnFinalClassAvoidNestedBlocksIllegalImport(sun.*)RedundantImportjava.langimports; the IDE flags theseTodoCommentTranslation.propertieskey parityJavadocVariableMissingJavadocMethodMissingJavadocexists only at HEAD, not in 2.50.0. Was suppressed anywayJspecifyMapStructMapperAnnotation(custom)On the "linting versus style" framing
The two tools do not divide that way, and a reviewer should not read the change that way.
Error Prone is not linting only.
Of the 82 checks now at ERROR, 12 carry Google's own
StandardTags.STYLEtag, read from the@BugPatternannotations in the 2.50.0 sources:ConstantField,EmptyCatch,MissingBraces,MissingOverride,MixedArrayDimensions,MultiVariableDeclaration,MultipleTopLevelClasses,PackageLocation,RemoveUnusedImports,SwitchDefault,UnnecessaryStaticImport,WildcardImportFour more carry
FRAGILE_CODE, and 64 carry no tag, because the attribute is optional.Varifier,UnnecessaryParentheses,TooManyParametersandLongLiteralLowerCaseSuffixare pure style too.Checkstyle was not style only. Its
codingcategory held 8 modules anddesignheld 4. Those are correctness and API rules.The real axis is what each tool can see:
There is a quality difference worth stating: Checkstyle judges without type information.
Its
EqualsHashCodematches on method names. Error Prone's resolves types and symbols. Same rule name, stronger guarantee.What the migration gains
///markdown comments directly.CheckReturnValue,ReferenceEquality,MissingOverride,UnusedVariable,Varifier,UseEnumSwitch, the varargs family, and the rest.compileJava compileTestJava.RequireExplicitNullMarkingand the customJspecifyOnTopLevelTypesenforced the same rule twice.Configuration layout
The block is grouped by topic, and alphabetical inside each group:
Of the 82, 43 rise from WARNING and 35 rise from DISABLED. Two (
NullAway,RequireExplicitNullMarking) come from the NullAway artifact, whose defaults are WARNING and SUGGESTION.Review notes
CheckReturnValueandSelfComparisonare already ERROR by default in Error Prone 2.50.0. They are listed so the policy is explicit and survives a release that lowers a default. Say the word and they come out.UnnecessarySemicolonis deliberately off. It replaces CheckstyleEmptyStatement, but Lombok makes it fire on every@Getterand@Setter: 1547 reports from 39 source positions.MissingOverridemust stay at ERROR. NullAway needs it for the exhaustive override checks.lombok.checkReturnValueAnnotation = lombokpairs withCheckReturnValueat ERROR. Verified:Error Prone matches the annotation by simple name, so
@lombok.CheckReturnValueis honoured. It generates nothing today, because the codebase has no@Withand no@Builder.Source changes
Five files, all mechanical:
@SuppressWarnings("checkstyle:MethodLength")entries removed fromGrantReconciler,GrantService,GrantReconcilerTestandHelmTest. Thejava:S3776entries stay.RoleReconcilerTest:private @Nullable <T> T getRoleFlagValue(→private <T> @Nullable T getRoleFlagValue(.A type-use annotation belongs after the type parameter. This is the only violation any newly enabled check found.
Build and infrastructure changes
build.gradle.ktscheckstyleplugin,apply(plugin = "checkstyle"), thetasks.withType<Checkstyle>block, thecheckstyleConfigconfiguration, thecheckstyleExtractConfigtask and thecheckstyle { }block are gone. The Error Prone block replaces themgradle/libs.versions.tomlcheckstyleConfigandcheckstyleremoved, versions and library entriessettings.gradle.ktsit.aboutbitsgroup only.gitignoreconfig/, the suppressions exception and!.idea/checkstyle-idea.xmlremoved.githooks/pre-commitcheckstyleMain checkstyleTest→compileJava compileTestJava.github/workflows/test.yml,release.ymlGITHUB_USER_NAMEandGITHUB_ACCESS_TOKENenv blocks, which fed the removed repositoryREADME.mdconfig/and.idea/checkstyle-idea.xmlTest scope
./gradlew --rerun-tasks :operator:compileJava :operator:compileTestJava :generated:compileJava- 0 Error Prone findings../gradlew build -x test- successful.compileJava compileTestJavaruns - configuration cache reused../gradlew tasks --all | grep -i checkstyle- nothing.UnnecessarySemicolontemporarily at ERROR the build failed witherror: [UnnecessarySemicolon].Method
Every candidate was compiled at WARN across all three source sets with the warning cap raised, and only checks at zero violations were promoted. Four measurement rounds, 83 candidates. Two produced findings:
UnnecessarySemicolon(excluded) andAnnotationPosition(one violation, fixed).