1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//! Diagnostic deduplication
//!
//! This module provides functionality for removing duplicate diagnostics
//! to avoid reporting the same issue multiple times.
use ;
/// Byte-distance threshold for cascade suppression.
///
/// Parse-error diagnostics whose start offsets fall within this many bytes
/// of the current cluster head are treated as downstream cascades and
/// suppressed. Only the first diagnostic in each cluster is kept.
///
/// # Rationale for 10 bytes
///
/// This threshold targets **intra-statement cascades**: when the parser
/// encounters a syntax error inside an expression it may emit several tightly-
/// clustered errors (e.g. `my $x = = 1;` can trigger two `UnexpectedToken`
/// errors both pointing at the same offset). After exact-duplicate removal
/// (pass 1) the remaining nearby errors are typically within a few bytes of
/// each other — well inside this threshold. Tokens in a single syntactic unit
/// rarely span more than 10 bytes in practice, so the threshold catches
/// same-expression noise without suppressing genuinely independent errors on
/// separate lines.
///
/// **Design note — why suppress entirely rather than downgrade to `Information`:**
/// An alternative approach would demote cascade errors to `Information` severity
/// instead of dropping them. This was considered and rejected: `Information`
/// diagnostics still appear as blue underlines in the editor gutter at positions
/// the user did not make a mistake, which creates confusing noise without adding
/// actionable context. Complete suppression is the right choice for cascade
/// errors — the root-cause error (the cluster head) is the only marker the
/// user needs. Lint and scope-analysis diagnostics are never suppressed.
const CASCADE_THRESHOLD_BYTES: usize = 10;
/// Parse-error diagnostic codes emitted by the parser layer.
///
/// Only diagnostics with these codes are considered candidates for cascade
/// suppression. Scope-analysis warnings and lint hints are never suppressed.
const PARSE_ERROR_CODES: & = &;
/// Returns `true` if this diagnostic was produced by the parser (not by a lint
/// or scope-analysis pass).
/// Suppress cascading parse-error diagnostics using location clustering.
///
/// After exact-duplicate removal the parser may still emit several tightly-
/// grouped diagnostics that all stem from a single syntax error (e.g. an
/// unclosed delimiter causes "unexpected token" errors on every subsequent
/// statement). This pass groups adjacent parse-error diagnostics by byte
/// proximity and retains only the first diagnostic in each cluster.
///
/// Algorithm:
/// 1. Separate diagnostics into parse-errors and everything else.
/// 2. Sort parse-errors by start byte offset.
/// 3. Walk the sorted list; start a new cluster whenever the current
/// diagnostic's start offset exceeds the cluster-head's start offset by
/// more than [`CASCADE_THRESHOLD_BYTES`].
/// 4. Recombine kept parse-errors with the untouched non-parse-error
/// diagnostics.
/// De-duplicate diagnostics to avoid reporting the same issue twice.
///
/// Performs two passes:
///
/// 1. **Exact deduplication** — removes diagnostics that share the same
/// range, severity, code, and message.
/// 2. **Cascade suppression** — groups adjacent parse-error diagnostics by
/// byte proximity and retains only the first in each cluster, suppressing
/// downstream noise caused by error-recovery.