public sealed class SilentCatchAnalyzerReports a catch that takes every exception and then never mentions it.
No guide page documents this yet — the page shows what the code says about itself.
Remarks
The rule is docs/plan/13-diagnostics.md § Discipline's: every catch either handles or logs with the exception object. That bullet claimed an analyzer enforced it for as long as it existed and no analyzer did (#344). This is the enforcement, and it is narrower than the sentence — deliberately, and the boundary is in the table below.
⚠ CA1031 is not this rule and could not be made into it. The BCL's "do not catch general exception types" fires on the shape of the clause and says nothing about the body, so it reports the very form doc 13 asks for — catch (Exception exception) followed by a log carrying exception — and stays silent on nothing this rule reports. It is also off in this repository: AnalysisLevel is latest-recommended, which does not enable it, and sixteen unfiltered broad catches compile clean in Core/ today to prove it. The seven #pragma warning disable CA1031 comments in the tree suppress a rule that is not running.
What is reported is one shape: the clause takes Exception (or is bare, which is the same reach), has no when filter to narrow it, never rethrows, and never names the exception it caught. Such a clause cannot have handled the failure it was handed, because it never looked at it — every failure the try can produce, including the ones nobody predicted, takes the same silent path. That is the shape this repository keeps being bitten by from the other side: fifteen renderers degraded silently until they were made to log, and PageResidency's own log events had never fired.
Four silences, each with a reason and a named negative test:
The body names the exception It reached a log, a message, a condition, or a field. ⚠ Naming it inside an interpolated string counts, and counts through a nested lambda — the check is the symbol the identifier binds to, not text, because a text scan gets exactly those two wrong. The body throws A throw; or a wrapped rethrow propagates the failure, which is the other half of "handles or logs". A when filter A filter is a written predicate about which failures this clause is for, which is the thing an untyped catch is missing. A narrower type ⚠ catch (OperationCanceledException) { } is not reported and that is a scope decision rather than an oversight. Naming a type is a decision about a named failure — cancellation, a socket closed under an accept, a codec's own error — and the twelve such clauses in Core/ are each written with the reason above them. Reporting them would make the rule something people learn to switch off, which is how the widest and most damaging form gets through with it.
Fields and properties (2)
public const string DiagnosticIdThe id reported for a catch that discards the exception.
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnosticsReturns a set of descriptors for the diagnostics that this analyzer is capable of producing.
Methods (1)
public override void Initialize(AnalysisContext context)Called once at session start to register actions in the analysis context.
Used by (2)
- AnalyzerHarnessVixen.Core.Diagnostics.Analyzers.Tests
- SilentCatchAnalyzerTestsVixen.Core.Diagnostics.Analyzers.Tests