Skip to content

Add linter and enforce it in CI#129

Merged
Lexer747 merged 7 commits into
ngraves95:mainfrom
Lexer747:pr-linter-formatter
May 9, 2026
Merged

Add linter and enforce it in CI#129
Lexer747 merged 7 commits into
ngraves95:mainfrom
Lexer747:pr-linter-formatter

Conversation

@Lexer747
Copy link
Copy Markdown
Collaborator

@Lexer747 Lexer747 commented Apr 13, 2026

Summary

I've noticed for a while that the code is inconsistent in it's styling and formatting, ideally to reduce general overhead in every diff I opine that a strict linter and formatter is much better than having to tell people during a pull request to "fix their formatting".

This PR does that by adding a checkstyle config and the gradle plugin. I specifically pinned it to version as according to the docs:

Checkstyle version JRE version
13.x 21 and above
11.x, 12.x 17 and above
10.x 11 and above
7.x, 8.x, 9.x 8 and above
6.x 6 and above
5.x 5 and above

As we use targetCompatibility: 1.11 this is JRE 11 so therefore we should use a checkstyle of 10.x hence I just set it as the latest that was released at the time of writing 10.26.1.

Doing it this was means that any IDE should work AND that CI will automatically tell any user that their change has issues.

Testing

Checkout the source files back to master, then run the linter/formatter (all the errors).

$attacktimer [pr-linter-formatter ≡]> git c main -- .\src\
$attacktimer [pr-linter-formatter ≡ +0 ~29 -0 ~]> .\gradlew checkstyleMain checkstyleTest

> Task :compileJava
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.

> Task :compileTestJava
Note: $attacktimer\src\test\java\com\attacktimer\TormentedDemonsTest.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

> Task :checkstyleMain
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AnimationData.java:264:61: Name 'spellBookAnimations' must match pattern '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'. [ConstantName]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AnimationData.java:265:54: Name 'notAttacks' must match pattern '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'. [ConstantName]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackBarStyle.java:10:1: File contains tab characters (this is the first instance). [FileTabCharacter]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackProcedure.java:28:29: '{' at column 29 should be on a new line. [LeftCurly]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerBarOverlay.java:16:3: File contains tab characters (this is the first instance). [FileTabCharacter]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerBarOverlay.java:44:1: Wrong order for 'net.runelite.api.SpriteID' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomeConfig.java:36:1: Wrong order for 'net.runelite.client.config.ConfigSection' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomeConfig.java:37:1: Wrong order for 'java.awt.Color' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomeConfig.java:42:1: File contains tab characters (this is the first instance). [FileTabCharacter]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomeConfig.java:58:16: Name 'TickNumberSettings' must match pattern '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'. [ConstantName]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomeConfig.java:176:16: Name 'AttackBarSettings' must match pattern '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'. [ConstantName]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomePlugin.java:45:1: Extra separation in import group before 'javax.inject.Inject' [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomePlugin.java:78:29: '{' at column 29 should be on a new line. [LeftCurly]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomePlugin.java:129:30: Name 'uiUnshowDebounceTicksMax' must match pattern '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'. [ConstantName]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomePlugin.java:229:32: '{' at column 32 should be on a new line. [LeftCurly]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomePlugin.java:303:34: '{' at column 34 should be on a new line. [LeftCurly]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomePlugin.java:436:58: '{' at column 58 should be on a new line. [LeftCurly]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomePlugin.java:437:34: '{' at column 34 should be on a new line. [LeftCurly]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomePlugin.java:441:46: '{' at column 46 should be on a new line. [LeftCurly]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomePlugin.java:456:38: '{' at column 38 should be on a new line. [LeftCurly]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomePlugin.java:468:30: '{' at column 30 should be on a new line. [LeftCurly]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomePlugin.java:470:34: '{' at column 34 should be on a new line. [LeftCurly]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomePlugin.java:472:24: '{' at column 24 should be on a new line. [LeftCurly]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomePlugin.java:481:51: '{' at column 51 should be on a new line. [LeftCurly]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomePlugin.java:482:38: '{' at column 38 should be on a new line. [LeftCurly]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomePlugin.java:484:28: '{' at column 28 should be on a new line. [LeftCurly]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomeTileOverlay.java:33:1: Wrong order for 'net.runelite.api.Player' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomeTileOverlay.java:39:1: Wrong order for 'javax.inject.Inject' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomeTileOverlay.java:40:1: Wrong order for 'java.awt.Dimension' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomeTileOverlay.java:42:1: Wrong order for 'java.awt.Font' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomeTileOverlay.java:73:89: '{' at column 89 should be on a new line. [LeftCurly]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomeTileOverlay.java:99:45: '{' at column 45 should be on a new line. [LeftCurly]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\AttackTimerMetronomeTileOverlay.java:117:38: '{' at column 38 should be on a new line. [LeftCurly]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\CastingSoundData.java:89:66: Name 'sounds' must match pattern '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'. [ConstantName]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\FontTypes.java:22:30: '{' at column 30 should be on a new line. [LeftCurly]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\PoweredStaves.java:33:1: Wrong order for 'com.google.common.collect.ImmutableMap' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\PoweredStaves.java:131:88: Name 'poweredStaves' must match pattern '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'. [ConstantName]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\Spellbook.java:44:59: Name 'books' must match pattern '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'. [ConstantName]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\VariableSpeed\BloodMoonSet.java:35:30: Name 'BloodMoonSetAnimId' must match pattern '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'. [ConstantName]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\VariableSpeed\Leagues.java:34:1: Extra separation in import group before 'net.runelite.api.Client' [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\VariableSpeed\RapidAttackStyle.java:31:1: Wrong order for 'com.attacktimer.AttackProcedure' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\VariableSpeed\TormentedDemons.java:32:1: Wrong order for 'com.attacktimer.AnimationData' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\VariableSpeed\TormentedDemons.java:36:1: Wrong order for 'com.attacktimer.ClientUtils.Utils' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\VariableSpeed\TormentedDemons.java:134:49: '{' at column 49 should be on a new line. [LeftCurly]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\VariableSpeed\TormentedDemons.java:172:34: Name 'VulTicksAfterEnd' must match pattern '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'. [ConstantName]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\VariableSpeed\VariableSpeed.java:29:1: Wrong order for 'com.attacktimer.AnimationData' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\VariableSpeed\VariableSpeed.java:33:28: '{' at column 28 should be on a new line. [LeftCurly]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\VariableSpeed\VariableSpeed.java:62:43: Name 'toApply' must match pattern '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'. [ConstantName]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\WeaponType.java:32:1: Wrong order for 'com.attacktimer.AttackStyle.ACCURATE' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\WeaponType.java:41:1: Wrong order for 'com.attacktimer.AttackType.RANGED' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\WeaponType.java:42:1: Wrong order for 'com.attacktimer.AttackType.MAGIC' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\WeaponType.java:47:1: Wrong order for 'net.runelite.api.EnumID' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\WeaponType.java:94:51: Name 'weaponTypes' must match pattern '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'. [ConstantName]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\WeaponType.java:136:69: Array should contain trailing comma. [ArrayTrailingComma]
[ant:checkstyle] [ERROR] $attacktimer\src\main\java\com\attacktimer\WeaponType.java:144:55: Array should contain trailing comma. [ArrayTrailingComma]

> Task :checkstyleMain FAILED

> Task :checkstyleTest
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\AttackTimerPluginTest.java:8:1: File contains tab characters (this is the first instance). [FileTabCharacter]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\BasicTests.java:32:1: Wrong order for 'org.junit.Assert.assertSame' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\BasicTests.java:37:1: Extra separation in import group before 'com.attacktimer.AttackTimerMetronomePlugin.AttackState' [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\BasicTests.java:37:1: Wrong order for 'com.attacktimer.AttackTimerMetronomePlugin.AttackState' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\BasicTests.java:39:1: Extra separation in import group before 'com.google.common.io.ByteArrayDataOutput' [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\BasicTests.java:42:1: Extra separation in import group before 'net.runelite.api.ChatMessageType' [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\EatTest.java:29:1: Wrong order for 'org.junit.Assert.assertSame' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\EatTest.java:30:1: 'org.junit.Test' should be separated from previous imports. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\EatTest.java:32:1: Extra separation in import group before 'com.attacktimer.AttackTimerMetronomePlugin.AttackState' [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\EatTest.java:32:1: Wrong order for 'com.attacktimer.AttackTimerMetronomePlugin.AttackState' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\EatTest.java:34:1: Extra separation in import group before 'net.runelite.api.ChatMessageType' [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\EatTest.java:57:17: Array should contain trailing comma. [ArrayTrailingComma]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\EnumTests.java:30:1: 'org.junit.Ignore' should be separated from previous imports. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\IntegrationTests.java:40:1: Wrong order for 'org.junit.Assert.assertArrayEquals' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\IntegrationTests.java:49:1: Extra separation in import group before 'com.google.common.io.ByteArrayDataOutput' [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\IntegrationTests.java:49:1: Wrong order for 'com.google.common.io.ByteArrayDataOutput' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\IntegrationTests.java:55:1: Extra separation in import group before 'net.runelite.api.Client' [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\IntegrationTests.java:131:27: Array should contain trailing comma. [ArrayTrailingComma]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\IntegrationTests.java:204:32: Name 'noAnimation' must match pattern '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'. [ConstantName]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\IntegrationTests.java:205:35: Name 'testdata' must match pattern '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'. [ConstantName]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\IntegrationTests.java:207:33: Name 'testMessagePrefix' must match pattern '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'. [ConstantName]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\IntegrationTests.java:208:33: Name 'testMessageSuffix' must match pattern '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'. [ConstantName]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\TormentedDemonsTest.java:35:1: Wrong order for 'org.junit.Assert.assertSame' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\TormentedDemonsTest.java:36:1: 'org.junit.Test' should be separated from previous imports. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\TormentedDemonsTest.java:38:1: Extra separation in import group before 'com.attacktimer.AttackTimerMetronomePlugin.AttackState' [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\TormentedDemonsTest.java:38:1: Wrong order for 'com.attacktimer.AttackTimerMetronomePlugin.AttackState' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\TormentedDemonsTest.java:42:1: Extra separation in import group before 'net.runelite.api.EnumComposition' [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\TormentedDemonsTest.java:129:27: Array should contain trailing comma. [ArrayTrailingComma]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\Update.java:30:1: Extra separation in import group before 'com.google.common.collect.ImmutableMap' [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\Update.java:30:1: Wrong order for 'com.google.common.collect.ImmutableMap' import. [ImportOrder]
[ant:checkstyle] [ERROR] $attacktimer\src\test\java\com\attacktimer\Update.java:45:55: Name 'updates' must match pattern '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'. [ConstantName]

> Task :checkstyleTest FAILED

FAILURE: Build completed with 2 failures.

1: Task failed with an exception.
-----------
* What went wrong:
Execution failed for task ':checkstyleMain'.
> A failure occurred while executing org.gradle.api.plugins.quality.internal.CheckstyleAction
   > Checkstyle rule violations were found. See the report at: file:///$attacktimer/build/reports/checkstyle/main.html
     Checkstyle files with violations: 17
     Checkstyle violations by severity: [error:55]


* Try:
> Run with --scan to get full insights.
==============================================================================

2: Task failed with an exception.
-----------
* What went wrong:
Execution failed for task ':checkstyleTest'.
> A failure occurred while executing org.gradle.api.plugins.quality.internal.CheckstyleAction
   > Checkstyle rule violations were found. See the report at: file:///$attacktimer/build/reports/checkstyle/test.html
     Checkstyle files with violations: 7
     Checkstyle violations by severity: [error:31]


* Try:
> Run with --scan to get full insights.
==============================================================================

BUILD FAILED in 6s
5 actionable tasks: 4 executed, 1 up-to-date

@Lexer747 Lexer747 force-pushed the pr-linter-formatter branch from 4fb91e8 to 38f8609 Compare April 14, 2026 16:59
@Lexer747
Copy link
Copy Markdown
Collaborator Author

@ngraves95 feel free to push back on this if you have another preferred option for linting/formatting - also add or remove the rules/lints from the checkstyle.xml (docs).

The only thing that checkstyle seems to lack which I would miss is unused static imports :( it's unfortunatly listed as something that cannot be supported https://checkstyle.sourceforge.io/checks/imports/unusedimports.html

@Lexer747 Lexer747 requested a review from ngraves95 April 14, 2026 19:44
@Lexer747 Lexer747 marked this pull request as ready for review April 14, 2026 19:44
@Lexer747 Lexer747 force-pushed the pr-linter-formatter branch from 4f3ce9c to 2d8cc1a Compare May 9, 2026 10:32
@Lexer747 Lexer747 merged commit 506d859 into ngraves95:main May 9, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant