Skip to content

feat: located analyzer-exception diagnostic (XX0000) replacing bare AD0001#366

Merged
Arthurvdv merged 5 commits into
mainfrom
feat/xx0000-analyzer-exception-diagnostic
Jun 24, 2026
Merged

feat: located analyzer-exception diagnostic (XX0000) replacing bare AD0001#366
Arthurvdv merged 5 commits into
mainfrom
feat/xx0000-analyzer-exception-diagnostic

Conversation

@Arthurvdv

Copy link
Copy Markdown
Member

Summary

When an ALCops analyzer throws (e.g. a NullReferenceException), the NAV SDK catches it and emits the generic AD0001 on app.json line 1 — giving no clue which object/line caused the failure. This PR makes analyzer exceptions diagnosable: they surface as a located per-cop XX0000 diagnostic (AC0000TA0000) at the analyzed object/line, with a message naming the failing analyzer and exception.

Approach

A reusable harness in ALCops.Common/Diagnostics/:

  • ALCopsDiagnosticAnalyzer — abstract base. Seals Initialize/SupportedDiagnostics; exposes InitializeAnalyzer(SafeAnalysisContext) + SupportedDiagnosticsCore; auto-appends the cop's XX0000 descriptor.
  • SafeAnalysisContext / SafeCompilationStartContext — decorators that wrap every registered callback in try/catch and report XX0000 at a context-appropriate location.
  • AnalyzerExceptionReporter — builds the diagnostic.
  • Per-cop {Cop}Analyzer bridge + XX0000 descriptor, Internal category, and resx strings wired into all 6 cops.

Adopting an analyzer is a uniform 3-line edit (no Register* changes). Only CaptionRequired (ApplicationCop) is converted in this PR; the other 92 analyzers adopt incrementally later via the documented recipe.

Design notes

  • Severity Info, enabled — visible, never breaks treat-warnings-as-errors builds.
  • Operation actions use new-hiding (the public params overload routes through internal SDK members); works because adopters type the param as SafeAnalysisContext.
  • SDK coupling accepted + documented — a new public-abstract Register* in a future SDK is a deliberate compile-time break (forces wrapping the new surface).
  • Builds on netstandard2.1/net8.0/net10.0, no #if guards.

Tests

Rules/AnalyzerExceptionHarness/ adds test-only throwing analyzers covering the symbol, operation (new-hiding), and CompilationStart-nested paths; each asserts AC0000 at the expected location. Full suite: 1170 tests pass, all 6 cops build in CI triple-target mode.

Docs (separate repo)

XX0000.md pages + index rows for all 6 cops are prepared on ../alcops.dev but not committed here (that repo has unrelated in-progress changes); to be landed via its own PR.

Out of scope

  • Converting the remaining 92 analyzers.
  • Fixing the underlying CaptionRequired NRE — AC0000 now reveals the culprit.

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

Arthurvdv and others added 5 commits June 24, 2026 13:58
Add ALCopsDiagnosticAnalyzer base class plus SafeAnalysisContext and
SafeCompilationStartContext decorators that wrap every registered analysis
callback in try/catch. An unhandled exception is converted into a located
XX0000 diagnostic at the symbol/node being analyzed instead of surfacing as
the SDK's AD0001 on app.json line 1.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a per-cop XX0000 AnalyzerException diagnostic (Info, enabled), a dedicated
Internal category, resx strings, and a thin {Cop}Analyzer bridge that supplies
the descriptor to the shared ALCopsDiagnosticAnalyzer base. No production
analyzer is converted yet; the scaffolding lets analyzers adopt the harness via
a uniform 3-line change.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Convert CaptionRequired to derive from ApplicationCopAnalyzer, overriding
SupportedDiagnosticsCore and InitializeAnalyzer. No Register* call changes.
An unhandled exception now surfaces as AC0000 at the analyzed object instead
of AD0001 on app.json.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add test-only throwing analyzers exercising the symbol, operation (new-hiding),
and CompilationStart-nested registration surfaces. Each asserts AC0000 is
reported at the analyzed object/line.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add analyzer-exception-harness.instructions.md (design, adoption recipe,
SDK-coupling note, fallback) and reference it from analyzer-development,
project-overview, and the instruction-maintenance index.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Arthurvdv Arthurvdv merged commit abb0c9f into main Jun 24, 2026
48 checks passed
@Arthurvdv Arthurvdv deleted the feat/xx0000-analyzer-exception-diagnostic branch June 24, 2026 12:29
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