Skip to content

fix(FC0004): regression fixtures for permission lists with compiler directives; CodeFix directive policy - #565

Merged
Arthurvdv merged 4 commits into
mainfrom
fix/fc0004-directive-regression
Sep 27, 2026
Merged

Arthurvdv merged 4 commits into
mainfrom
fix/fc0004-directive-regression

Conversation

@Arthurvdv

Copy link
Copy Markdown
Member

Summary

This PR adds FC0004 regression fixtures for permission lists that contain compiler directives. It also adds a house policy for every CodeFix: keep every directive and any disabled text in the edited span, or do not offer the fix.

No analyzer, CodeFix or Common C# code changed.

Verification

  • v1.1.0: reproducible. The FC0004 fix always rebuilt the list with PermissionSyntaxHelper.BuildMultiLinePermissionValue, which strips every entry's leading and trailing trivia. A directive line is leading trivia of the token after it, so #if not CLEAN… and #pragma warning disable AL0432 lines inside the list were deleted.
  • Since v1.2.0: not reproducible. The AZ-order rewrite (PermissionSyntaxHelper.TryBuildRegionTree) refuses any list with a non-region directive in an entry's leading trivia or in the ; token's leading trivia. For such a list the analyzer reports nothing, so the fix never runs. Such lists are also not sorted, which matches AZ AL Dev Tools.

What the fixtures pin

  • NoDiagnostic/ActiveIfWithPragmaAroundEntry.al: the issue's exact layout. An unsorted list has one entry wrapped in #if not CLEAN25 + #pragma warning disable/restore AL0432, and that entry's table is marked ObsoleteState = Pending.
  • NoDiagnostic/IfAroundLastEntry.al: an unsorted list whose #endif lands in the ; token's leading trivia.
    • Both passed on the first run, which is expected: they guard against the v1.1.0 behaviour rather than drive a code change.
  • HasFix/PreserveDirectivesAroundProperty: a multi-line list with #pragma warning disable/restore around the property. This covers the layout-preserving reorder path.
  • HasFix/SingleLineWithDirectivesAroundProperty: a single-line list with #if not CLEAN25/#endif around the property. This covers the multi-line rebuild path.
    • Red step: expected.al first left out one directive line. Both tests failed with TransformedCodeDifferentThanExpectedException naming the missing line, then passed once the line was restored.
    • Variants with #if and #pragma swapped behaved the same, so the PR keeps one of each.

Guidance added

  • .claude/rules/codefix-development.md: new section "Compiler directives and disabled text". It covers:

    • the policy (preserve, else bail out);
    • where directives live;
    • which calls drop them, including what each SyntaxRemoveOptions value keeps (per SyntaxNodeRemover.AddDirectives);
    • detection APIs, verified yes at every SDK version in the nav-sdk-docs reference tables;
    • the FC0004 and LC0095 preservation patterns.

    The "Where to find each fix shape" table also gets a new row.

  • .claude/rules/testing.md: a mandatory directive fixture set for fixes that remove, move or rebuild nodes: active #if, inactive #if, a #pragma pair and a #region pair.

  • .claude/skills/new-codefix/SKILL.md: a design-gate question, a Step 3 test requirement and a Common Mistakes row.

  • REVIEW.md (house section): a new row for trivia-stripping fixes without a directive gate or directive fixtures. The severity sentence now also counts "what a CodeFix produces" as correctness.

  • .claude/rules/diagnostics/fc0004-permission-declaration-order.md: the directive non-report now explains both #if branches. The CodeFix table gets a row on directives outside the list.

Fixes #454

Audit of the other CodeFixes: #564

Checks

  • dotnet test src/ALCops.FormattingCop.Test/ --filter "FullyQualifiedName~PermissionDeclarationOrder": Passed! - Failed: 0, Passed: 49, Skipped: 0, Total: 49, Duration: 1 s - ALCops.FormattingCop.Test.dll (net10.0)
  • dotnet build ALCops.sln: succeeded, 0 errors.
  • dotnet format ALCops.sln --verify-no-changes: exit 0.
  • pwsh .claude/scripts/Validate-Rules.ps1: OK: 55 rules files (15 guides, 40 rule docs) pass all checks.
  • No analyzer or Common C# changed, so no multi-TFM build was needed.
  • The alcops.dev FC0004 page already documents that lists with #if/#pragma are not checked, so no docs PR is needed.

🤖 Generated with Claude Code

Arthurvdv and others added 4 commits September 27, 2026 07:48
… fix rewrites

NoDiagnostic cases pin that unsorted lists with an active #if/#pragma
around an entry, or an #endif in the ; token's leading trivia, are not
reported (so the fix cannot delete those lines). HasFix cases pin that
#pragma and #if lines around the whole property survive both the
layout-preserving reorder and the single-line to multi-line rebuild.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A CodeFix keeps every directive and any disabled text in the span it
edits, or does not register. codefix-development.md explains where
directives live, which calls drop them (including what each
SyntaxRemoveOptions value keeps) and how to detect them; testing.md
makes the directive fixture set mandatory for fixes that remove, move
or rebuild nodes; the new-codefix skill and REVIEW.md enforce both.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Arthurvdv
Arthurvdv merged commit 5d3de04 into main Sep 27, 2026
40 checks passed
@Arthurvdv
Arthurvdv deleted the fix/fc0004-directive-regression branch September 27, 2026 06:39
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.

FC0004 Code action removes compiler directives

1 participant