Skip to content

test: add ArchUnit rule to prevent primitive types on @Option fields + fix object versions#2517

Open
maxandersen wants to merge 2 commits into
mainfrom
test/archunit-no-primitive-options
Open

test: add ArchUnit rule to prevent primitive types on @Option fields + fix object versions#2517
maxandersen wants to merge 2 commits into
mainfrom
test/archunit-no-primitive-options

Conversation

@maxandersen

Copy link
Copy Markdown
Collaborator

Summary

Add an ArchUnit test (CliArchitectureTest) that ensures all Aesh CLI annotation fields (@Option, @Argument, @Arguments, @OptionList, @OptionGroup) use boxed types instead of Java primitives.

Problem

Primitive types have implicit defaults (false, 0, etc.) which make it impossible for JBangDefaultValueProvider to distinguish "user didn't pass the flag" from "user explicitly set the default value". This breaks config-file overriding — a config value can never be negated from the CLI because the primitive default shadows it.

For example, with boolean insecure, setting insecure=true in jbang.properties works, but passing --no-insecure on the CLI can't override it because false (the primitive default) is indistinguishable from "not set".

What this PR adds

  • ArchUnit dependency (archunit-junit5:1.4.0) in build.gradle
  • CliArchitectureTest with 5 rules (one per Aesh annotation), checking all 8 Java primitive types

Current violations detected

The test currently fails intentionally to document the 36 existing violations:

  • 35 boolean fields that should be Boolean
  • 1 int field (Deps.max) that should be Integer

Example violation message:

dev.jbang.cli.BaseCommand.insecure: @Option field must not be primitive (boolean);
use Boolean so JBangDefaultValueProvider can distinguish 'not set' from the default value

Next steps

The actual migration of primitive → boxed types should be done in a follow-up PR, with null checks added where each field is read.

Refs #2504

@coderabbitai

coderabbitai Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are limited based on label configuration.

🏷️ Required labels (at least one) (1)
  • ai-review

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5528f0ba-b0f7-41f0-8b02-b2603f614d2a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Add CliArchitectureTest that ensures all Aesh CLI annotation fields
(@option, @argument, @arguments, @OptionList, @OptionGroup) use boxed
types instead of primitives.

Primitive types have implicit defaults (false, 0, etc.) making it
impossible for JBangDefaultValueProvider to distinguish 'not set' from
'explicitly set to the default'. This breaks config-file overriding.

Currently detects 36 violations: 35 boolean fields and 1 int field
that should be Boolean/Integer respectively.

Refs #2504
@maxandersen maxandersen force-pushed the test/archunit-no-primitive-options branch from 9c76e69 to 8239c27 Compare June 7, 2026 08:18
…ValueProvider

Change all boolean/int @Option-annotated fields to use boxed types
(Boolean/Integer) so JBangDefaultValueProvider can distinguish between
'not set' (null) and 'explicitly set to default' (false/0).

Files changed:
- BaseCommand.java: boolean insecure → Boolean
- JBang.java: boolean versionRequested → Boolean
- Edit.java: boolean live, noOpen, sandbox → Boolean
- Init.java: boolean force, edit → Boolean
- Info.java: boolean dependenciesOnly, open → Boolean
- Version.java: boolean checkForUpdate, update → Boolean
- Alias.java: boolean force (AliasAdd), showOrigin (AliasList) → Boolean
- Catalog.java: boolean force (CatalogAdd), showOrigin (CatalogList) → Boolean
- Config.java: boolean global (BaseConfigCommand), showOrigin, showAvailable → Boolean
- Template.java: boolean force, showOrigin, showFiles, showProperties → Boolean
- App.java: boolean force, noBuild (AppInstall), force (AppSetup) → Boolean
- Cache.java: boolean all → Boolean
- Jdk.java: boolean force, available, details, forVersion → Boolean
- Export.java: boolean force → Boolean
- Wrapper.java: boolean force → Boolean
- DependencyInfoMixin.java: boolean ignoreTransitiveRepositories → Boolean
- CatalogFileOptionsMixin.java: boolean global → Boolean
- Deps.java: int max → Integer

All usages updated to use Boolean.TRUE.equals() pattern for null-safe
evaluation. Also fixed an unboxing NPE in Jdk.JdkList where 'available'
was used in a ternary without null-check.
@maxandersen maxandersen force-pushed the test/archunit-no-primitive-options branch from dc91dd6 to 210e870 Compare June 7, 2026 14:33
@maxandersen maxandersen changed the title test: add ArchUnit rule to prevent primitive types on @Option fields test: add ArchUnit rule to prevent primitive types on @Option fields + fix object versions Jun 7, 2026
@quintesse

Copy link
Copy Markdown
Contributor

Never heard of ArchUnit before, pretty neat 👍

@maxandersen

Copy link
Copy Markdown
Collaborator Author

I have mentioned it before :) but hadn't had a good usecase to find problems and now realize it's output is great for driving LLMs to fix stuff. So perfect storm!

Note: @stalep working on fix in aesh so we hopefully don't need to keep this.

@quintesse

Copy link
Copy Markdown
Contributor

I have mentioned it before

As you can see I don't always listen very well 😅

@maxandersen

Copy link
Copy Markdown
Collaborator Author

It's more me sucking at speaking well :)

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.

2 participants