You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* Detects thrown exceptions from `throw` statements, `[Throws]` annotations, and `<exception>` XML docs.
10
+
* Ensures each exception is either **caught** in a surrounding `try/catch` or **declared** with `[Throws]`.
11
+
* Produces diagnostics such as **unhandled exceptions** (`THROW001`) and **bad practices** (e.g. `THROW004` for `throw new Exception()`).
12
+
13
+
2.**Control Flow Analysis (optional)**
14
+
15
+
* Performs lightweight reachability analysis to refine diagnostics.
16
+
* Detects **redundant catch clauses** and **unreachable code** (with IDE gray‑out support).
17
+
* Improves accuracy by reporting only exceptions that are truly reachable in context.
18
+
* This analysis can be **disabled** in configuration if only the basic handling checks are desired.
19
+
20
+
---
21
+
3
22
## `Throws` attribute
4
23
5
24
The `[Throws]` attribute is the contract that tells that a method, property accessor, local function, or lambda expression might throw one or more specified exceptions.
@@ -8,7 +27,7 @@ Placing a `Throws` declaration on a declaration will mark the specified exceptio
8
27
9
28
---
10
29
11
-
## Unhandled exceptions
30
+
## Unhandled exceptions (Core analysis)
12
31
13
32
The diagnostic for *Unhandled exception types* is **`THROW001`**.
14
33
@@ -36,7 +55,7 @@ public void TestMethod()
36
55
37
56
---
38
57
39
-
## Handling exceptions
58
+
## Handling exceptions (Core analysis)
40
59
41
60
### Exception declarations (`[Throws]`)
42
61
@@ -125,10 +144,12 @@ public void TestMethod() => throw new InvalidOperationException();
125
144
126
145
---
127
146
128
-
## Redundant or invalid handling
147
+
## Redundant or invalid handling (Control flow analysis)
129
148
130
149
### Redundant catch clauses
131
150
151
+
Detected only with control flow analysis:
152
+
132
153
***Typed catch never matched** → **`THROW009`**
133
154
134
155
```c#
@@ -147,6 +168,8 @@ public void TestMethod() => throw new InvalidOperationException();
147
168
148
169
### Redundant exception declarations
149
170
171
+
Control flow analysis is also used to determine whether declarations are truly necessary:
172
+
150
173
***Declared but never thrown** → **`THROW012`**
151
174
152
175
```c#
@@ -158,33 +181,31 @@ public void TestMethod() => throw new InvalidOperationException();
158
181
159
182
***Already covered by base type** → **`THROW008`**
160
183
161
-
Flow analysis is used to determine whether declared exceptions are necessary based on actual code paths.
162
-
163
-
### Invalid placement
184
+
### Invalid placement (Core analysis)
164
185
165
186
***Throws on full property (instead of accessor)** → **`THROW010`**
Redundant handling is also reported when more general types make specific ones unnecessary (**`THROW008`**).
204
+
Redundant handling is also reported when more general types make specific ones unnecessary (**`THROW008`**, via control flow analysis).
184
205
185
206
---
186
207
187
-
## Interop: XML documentation support
208
+
## Interop: XML documentation support (Core analysis)
188
209
189
210
Exceptions from XML documentation are outwardly treated as *declared* by the consumer. This provides compatibility with the .NET class library and third‑party code.
190
211
@@ -215,7 +236,94 @@ Disabling removes XML doc interop, including .NET class library coverage.
215
236
216
237
---
217
238
218
-
## Ignored exceptions
239
+
### Property heuristics
240
+
241
+
When `<exception>` documentation is applied to a **property**, the analyzer uses text‑based heuristics to decide which accessor receives the implied `[Throws]`:
242
+
243
+
* If the text mentions **“get”**, **“gets”**, **“getting”**, or **“retrieved”** → `[Throws]` is applied to the **getter**.
244
+
* If the text mentions **“set”**, **“sets”**, or **“setting”** → `[Throws]` is applied to the **setter**.
245
+
* If **no keywords are found**:
246
+
247
+
* If the property has only a **getter** or only a **setter** → `[Throws]` applies to that accessor.
248
+
* If the property has both → the analyzer **defaults to the getter**.
249
+
250
+
#### Examples
251
+
252
+
**Setter keyword**
253
+
254
+
```c#
255
+
/// <exceptioncref="InvalidOperationException">
256
+
/// Thrown if the value cannot be **set**.
257
+
/// </exception>
258
+
publicintValue { get; set; }
259
+
260
+
// Analyzer interprets this as:
261
+
// [Throws(typeof(InvalidOperationException))]
262
+
// set { ... }
263
+
```
264
+
265
+
**Getter keyword**
266
+
267
+
```c#
268
+
/// <exceptioncref="InvalidOperationException">
269
+
/// Thrown if the value cannot be **retrieved**.
270
+
/// </exception>
271
+
publicintValue { get; set; }
272
+
273
+
// Analyzer interprets this as:
274
+
// [Throws(typeof(InvalidOperationException))]
275
+
// get { ... }
276
+
```
277
+
278
+
**No keyword, defaults to getter**
279
+
280
+
```c#
281
+
/// <exceptioncref="InvalidOperationException">
282
+
/// Thrown if the property is in an invalid state.
283
+
/// </exception>
284
+
publicintValue { get; set; }
285
+
286
+
// Analyzer interprets this as:
287
+
// [Throws(typeof(InvalidOperationException))]
288
+
// get { ... }
289
+
```
290
+
291
+
---
292
+
293
+
#### Expression‑bodied properties
294
+
295
+
Expression‑bodied properties (`=>`) are treated as a single accessor:
296
+
297
+
* If it has only a `get` → `[Throws]` applies to the getter.
298
+
* If it has only a `set` (rare, but possible with `init` or `set =>`) → `[Throws]` applies to the setter.
@@ -276,3 +384,36 @@ public int TestProp => throw new InvalidOperationException();
276
384
```
277
385
278
386
This is treated as valid when there is only a `get` accessor.
387
+
388
+
> ℹ️ When exceptions are inferred from **XML documentation**, the same [property heuristics](#property-heuristics) apply to expression‑bodied properties: if only a `get` is present, exceptions are mapped to the getter; if only a `set` is present, exceptions are mapped to the setter.
389
+
390
+
---
391
+
392
+
## Configuration
393
+
394
+
Certain features can be toggled in `CheckedExceptions.settings.json`.
395
+
396
+
### Disable XML documentation interop
397
+
398
+
```json
399
+
{
400
+
"disableXmlDocInterop": true
401
+
}
402
+
```
403
+
404
+
Disables XML doc interop, including .NET class library coverage.
405
+
406
+
### Disable control flow analysis
407
+
408
+
```json
409
+
{
410
+
"disableControlFlowAnalysis": true
411
+
}
412
+
```
413
+
414
+
Disables the optional flow‑sensitive analysis.
415
+
When set, the analyzer will still report **unhandled exceptions** and enforce `[Throws]` contracts, but will no longer:
0 commit comments