Skip to content

feat(AC0033,AC0034): report Rest Client and Telemetry usage without a required interface implementation - #568

Merged
Arthurvdv merged 5 commits into
mainfrom
feat/ac0033-ac0034-required-interface-implementation
Sep 27, 2026
Merged

Arthurvdv merged 5 commits into
mainfrom
feat/ac0033-ac0034-required-interface-implementation

Conversation

@Arthurvdv

@Arthurvdv Arthurvdv commented Sep 27, 2026 •

Copy link
Copy Markdown
Member

Summary

Two new ApplicationCop rules on one shared analyzer (RequiredInterfaceImplementation), implementing Rule 3 of discussion #405 (the per-app existence check). Rules 1 and 2 of that discussion stay out of scope; Rule 2 (per-variable Initialize(Handler) flow tracking) is a separate follow-up because it needs a different, body-walking mechanism.

ID Rule Reports when
AC0033 RestClientRequiresHttpClientHandler An application object declares a variable, local, parameter or return value of Codeunit "Rest Client" (2350) and no codeunit in the app implements "Http Client Handler". Without one, the System Application's default handler sends the request, so the external-call permission and outgoing web service telemetry are attributed to the System Application instead of the app.
AC0034 TelemetryRequiresTelemetryLogger Same shape for Codeunit Telemetry (8711) / "Feature Telemetry" (8703) versus "Telemetry Logger". Without a registered logger for the publisher, Telemetry Loggers Impl. logs warning 0000G7K and discards the message.

Design

  • One diagnostic per rule per application object, reported at the object name; an object using both codeunits without either implementation gets both diagnostics.
  • Trigger codeunits are matched on object id and name; the required interface is matched by name (SemanticFacts.IsSameName). Only codeunits declared in the compiling app count as implementations; dependencies never do.
  • Skips obsolete objects and codeunits with Subtype = Test or TestRunner (mock handlers/loggers usually live in test libraries).
  • Severity Warning, enabled by default, category Design, no settings, no CodeFix (a generated handler/logger object has no deterministic location, name or namespace).
  • Performance: CompilationStart creates a per-compilation read-only Lazy index of implemented interfaces from GetDeclaredApplicationObjectSymbols(); a self-contained symbol action per object walks the object's declared symbols (GetMembers() with a descent allow-list) without any syntax walking or binding, and only consults the index when the object actually uses a trigger codeunit. No accumulate-then-report state, so partial-analysis passes are safe.
  • EnumProvider.CodeunitSubtypeKind gains TestRunner.

Deliberate non-reports

Codeunit::"Rest Client" object references without a variable, arrays/lists of the codeunit, interface-typed variables, implementations provided by a dependency app (suppress via ruleset or pragma), and whether the handler/logger is actually passed to Initialize/registered (existence only).

Verification

  • TDD: the first commit (wiring, stub analyzer, 46 fixtures) ran red — Failed: 26, Passed: 20 (all 26 HasDiagnostic cases failing, all 20 NoDiagnostic passing); after the implementation commit Passed: 46 on net10.0 and on the net8.0 leg (GITHUB_ACTIONS=true … -p:NavTargetFramework=net8.0).
  • dotnet build ALCops.sln clean; ApplicationCop and Common Release builds with ContinuousIntegrationBuild=true (netstandard2.1 / net8.0 / net10.0) clean; dotnet format ALCops.sln --verify-no-changes clean; full dotnet test ALCops.sln green; Validate-Rules.ps1 OK.
  • An ad-hoc NoException pass over all 46 fixtures (markers stripped) showed no swallowed analyzer exceptions.
  • Code review (Sonnet, effort high) run before opening this PR; its two findings (a CodeunitSubtypeKind fallback that resolved to Normal, and a duplicated member walk) are addressed in the last commit.

Docs: companion pages in ALCops/alcops.dev#193.

🤖 Generated with Claude Code

Arthurvdv and others added 4 commits September 27, 2026 10:59
…ixtures

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

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ember walk per object

A CodeunitSubtypeKind member missing from the loaded SDK resolved to Normal (0),
so the Test/TestRunner exemption would have matched every codeunit. The members
now fall back to an out-of-range value, like SymbolKind does. The analyzer also
walks an object's declared members once for both rules instead of once per rule.

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

Both messages now name the object as 'the "X" codeunit' like the other
ApplicationCop messages, and AC0034 states what actually happens without a
registered logger: the message is discarded and only warning 0000G7K is logged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Arthurvdv
Arthurvdv merged commit 0764aae into main Sep 27, 2026
40 checks passed
@Arthurvdv
Arthurvdv deleted the feat/ac0033-ac0034-required-interface-implementation branch September 27, 2026 10:20
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