Skip to content

fix(LC0092): skip platform-named action areas, system actions and layout areas - #541

Merged
Arthurvdv merged 6 commits into
mainfrom
fix/lc0092-action-area-naming
Sep 12, 2026
Merged

Arthurvdv merged 6 commits into
mainfrom
fix/lc0092-action-area-naming

Conversation

@Arthurvdv

@Arthurvdv Arthurvdv commented Sep 11, 2026

Copy link
Copy Markdown
Member

Fixes #537

Root cause

Every node inside an actions { } block is a single SymbolKind.Action symbol; IActionSymbol.ActionKind is the only thing that tells area apart from group, action, separator, actionref, customaction, systemaction and fileuploadaction. SymbolKind.Control is shaped the same way, with IControlSymbol.ControlKind separating the layout area from groups, fields and parts.

AnalyzeAction and AnalyzeControl never read those kinds, so a custom NamingPatterns.Action pattern such as act[A-Za-z0-9] was applied to area(Processing) — a name the platform fixes — and the Control pattern to area(Content). With the built-in defaults the same bug fires whenever an area is written lowercase (area(processing)), because ^[A-Z] fails.

Change

AnalyzeAction now skips:

  • ActionKind.Area — the name selects an ActionAreaKind member.
  • ActionKind.SystemAction — the name selects a SystemActionKind member.
  • ActionKind.Group whose name is a predefined promoted category (Category_New, Category_Process, Category_Report, Category_Category4 .. Category_Category20) — the name binds the group to that platform category slot. This is the same skip AC0011 already applies; the names come from SyntaxFacts.PromotedCategoriesSynthesizedSymbolNames, which the SDK builds with SemanticFacts.NameEqualityComparer.

AnalyzeControl skips ControlKind.Area.

Everything else stays as it was: ordinary groups, separators, action references, custom and file-upload actions remain checked under Action, and every control kind other than the layout area under Control. No new naming targets, so alcops.json and alcops.schema.json are unchanged.

EnumProvider.ActionKind gains SystemAction. The member is absent from the oldest supported SDK, so it is resolved through the string overload with an explicit out-of-range sentinel — default(ActionKind) is Area, and falling back to it would make every action area read as a system action on the netstandard2.1 build.

Tests

New fixtures under src/ALCops.LinterCop.Test/Rules/NamingPattern/, all of which failed before the analyzer change:

Fixture What it locks in
NoDiagnostic/ActionAreaLowerCase.al area(processing) is not flagged by the default pattern
NoDiagnostic/ControlAreaLowerCase.al area(content) is not flagged by the default pattern
NoDiagnostic/ActionAreaCustomPattern.al the issue's repro, with the issue's alcops.json
NoDiagnostic/ControlAreaCustomPattern.al layout area under a custom Control pattern
NoDiagnostic/PromotedCategoryGroupCustomPattern.al area(Promoted) { group(Category_Process) }
NoDiagnostic/SystemActionCustomPattern.al systemaction(OK) on a ConfigurationDialog page (gated at SDK 16.2.31: earlier SDKs reject the page type as a feature under development, AL0574)
HasDiagnostic/ActionGroupCustomPattern.al ordinary groups and actions are still checked with the custom pattern

The custom-settings fixtures share one alcops.json that carries the issue's Action pattern, a Control pattern and the pre-existing EnumValue pattern.

Verification

  • dotnet test src/ALCops.LinterCop.Test/ — 359 passed, 2 skipped, 0 failed.
  • dotnet build ALCops.sln — succeeded, 0 errors.
  • dotnet format ALCops.sln --verify-no-changes — clean.
  • dotnet build src/ALCops.Common and src/ALCops.LinterCop with -c Release -p:ContinuousIntegrationBuild=truenetstandard2.1, net8.0 and net10.0 all succeed with 0 warnings.
  • pwsh .claude/scripts/Validate-Rules.ps1 — OK.

Documentation for alcops.dev: ALCops/alcops.dev#181

🤖 Generated with Claude Code

…out areas

Every node inside an actions block is one SymbolKind.Action symbol, and
every node inside a layout block is one SymbolKind.Control symbol, so the
rule checked area, group, actionref, separator and systemaction names
against the Action target and layout areas against the Control target.
Those names are picked by the platform, not by the developer: an action
area name comes from ActionAreaKind, a system action name from
SystemActionKind, a layout area name from the page layout, and a group
named Category_Process binds the group to that promoted-category slot.

AnalyzeAction and AnalyzeControl now read IActionSymbol.ActionKind and
IControlSymbol.ControlKind and skip those kinds. Ordinary groups,
separators, action references, custom and file-upload actions stay
checked under Action, and every other control kind under Control, so no
new naming target and no settings-schema change is needed.

EnumProvider gains ActionKind.SystemAction, resolved through the string
overload with an out-of-range sentinel because the member is absent from
the oldest supported SDK and default(ActionKind) is Area.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Arthurvdv and others added 5 commits September 11, 2026 16:40
…ConfigurationDialog

SDKs 14.0 through 16.2.28 reject PageType = ConfigurationDialog as a feature
under development (AL0574), so the fixture only compiles from 16.2.31, where
the compiler downgrades that to a public-preview warning.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…inel

Both enums have a dispatchable zero member (Area), so a member absent from
the loaded SDK fell back to it and made every comparison against an action
or layout area true. Route every member of both nested classes through a
Parse helper with an out-of-range Unresolved sentinel, the way SymbolKind
already does.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
AC0011 kept a hand-lowercased copy of SyntaxFacts.PredefinedActionCategoryNames
and lowercased every name it tested, while LC0092 queried the SDK set directly.
Both now call IActionSymbol.IsPredefinedPromotedCategoryGroup(), which wraps the
SDK's own case-insensitive set, so the two cops cannot drift apart.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The 12.1 and 14.0 claims about systemaction and the ConfigurationDialog page
type had no evidence behind them; the availability tables only record absent
at 12.0 and present by 16.0. Also removes a deliberate non-report bullet that
restated the design-decision row and listed what the rule checks, not why.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Both custom-settings test methods built the same MemoryFileSystem fixture
inline; CreateFixtureWithSettings mirrors the helper the sibling
EventSubscriberNamingPattern tests already use.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Arthurvdv
Arthurvdv merged commit 393da07 into main Sep 12, 2026
38 checks passed
@Arthurvdv
Arthurvdv deleted the fix/lc0092-action-area-naming branch September 12, 2026 09:37
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.

[Bug]: LC0092 false positive for Action Areas - this is invalid as Areas are pre-defined by Microsoft

1 participant