Skip to content

fix(lint): preserve underscores and honor mixed_case_exceptions in pascal-case-struct - #16578

Open
gomesalexandre wants to merge 1 commit into
foundry-rs:masterfrom
gomesalexandre:fix_pascal_case_struct_underscores_and_exceptions
Open

fix(lint): preserve underscores and honor mixed_case_exceptions in pascal-case-struct#16578
gomesalexandre wants to merge 1 commit into
foundry-rs:masterfrom
gomesalexandre:fix_pascal_case_struct_underscores_and_exceptions

Conversation

@gomesalexandre

Copy link
Copy Markdown
Contributor

What

pascal-case-struct had two bugs, both in crates/lint/src/sol/naming.rs / crates/lint/src/sol/info/pascal_case.rs:

  1. Underscores weren't preserved. check_pascal_case was the only one of the three naming helpers (check_pascal_case, check_screaming_snake_case, check_mixed_case) that didn't call the shared preserve_underscores helper. A struct named _PascalCase got flagged with a MachineApplicable suggestion to rename to PascalCase — colliding with an already-existing struct of that exact name in the same contract. The existing StructPascalCase.sol fixture was pinning exactly this broken suggestion (struct PascalCase at one line, struct _PascalCase flagged suggesting PascalCase at another).

  2. mixed_case_exceptions was never consulted. mixed-case-function/mixed-case-variable both respect the configurable acronym allowlist (ERC, URI, etc. by default) via LintSpecificConfig, but pascal-case-struct never received the config at all — so struct ERC20Data gets flagged and suggested as Erc20Data.

Fix

  • check_pascal_case now calls preserve_underscores, matching its two siblings.
  • pascal_case.rs gained a PascalCaseStructPass wrapping Arc<LintSpecificConfig>, wired through register_lints!'s constructor mechanism exactly the way mixed_case.rs's two passes already do — including the same pre/post AsUpperCamelCase pattern-exception matching (adjusted for full PascalCase rather than lowerCamelCase).
  • Updated StructPascalCase.sol/.stderr (stderr regenerated via cargo test -p forge --test ui -- --bless) to cover both fixes: an _pascalCase case (proves the underscore is preserved in a real suggestion, not just a no-op passthrough) and an ERC20Data case (proves the exception now applies). The previously-colliding _PascalCase case is no longer flagged at all, since it already satisfies PascalCase-with-preserved-underscore.

Testing

  • cargo test -p forge-lint --lib — 11/11 passing, including new pascal_case_preserves_underscores unit tests.
  • Full fixture UI suite (cargo test -p forge --test ui) — 97/97 passing after the bless regeneration; confirmed the blessed diff only touches the one line that changed (the other already-flagged invalid cases — pascalCase, pascalcase, pascal_case, PASCAL_CASE, PASCALCASE — are unaffected).
  • Manually re-verified: s.find(pattern) on an empty pre/post, a pattern at the very start/end of the string, and a pattern longer than the input all resolve safely (no panic, no false match) — same as the pre-existing mixed_case.rs implementation this mirrors.

Note on review

Ran a synchronous Codex adversarial pass on this diff. It got partway through independently cross-referencing the exact mixed_case.rs pattern this PR mirrors before hitting a transient "model at capacity" error and never returned a final verdict. Did a manual self-review of the edge cases it was mid-way through checking (pattern-boundary matching, empty pre/post) rather than re-run it — noting this honestly rather than claiming a completed automated review.

closes nothing — filed independently, dupe-checked clean (no existing issue/PR on this).

…scal-case-struct

check_pascal_case never called preserve_underscores unlike its two
siblings (check_screaming_snake_case, check_mixed_case), so a struct
named _PascalCase would be flagged with a MachineApplicable suggestion
to rename to PascalCase - colliding with an already-existing struct of
that name in the same file. The existing StructPascalCase.sol fixture
was pinning exactly this broken suggestion.

pascal_case.rs also never consulted LintSpecificConfig.mixed_case_exceptions
(the acronym allowlist mixed-case-function/mixed-case-variable already
use), so struct names like ERC20Data were flagged and suggested as
Erc20Data.

Fixed check_pascal_case to preserve underscores like its siblings, and
wired PascalCaseStructPass through the same Arc<LintSpecificConfig>
pattern mixed_case.rs already uses, including its pre/post acronym-
exception matching. Updated the fixture (regenerated stderr via
--bless) to cover both fixes and removed the collision.
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

✅ Changelog found

The deterministic check will validate the changed entry.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant