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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
//! Helpers shared by rules that scan string-literal / comment text.
//!
//! [`emit_flagged_chars`] is used by the Unicode-ellipsis rules that
//! scan a contiguous stretch of text (`unicode_ellipsis_in_comments`
//! and `unicode_ellipsis_in_panic_messages`): walk it, emit a
//! diagnostic for each flagged character, and offer the same `...`
//! autofix. The per-character logic is identical; the only per-rule
//! pieces are the lint name, a context label, and how to turn a byte
//! offset within the text into a [`Span`].
//!
//! [`emit_flagged_char`] is the single-character core, factored out so
//! a rule that does its own scanning — `unicode_ellipsis_in_docs`,
//! which must consult a markdown code-region mask and a fallible
//! span map before emitting — shares the exact message, suggestion,
//! and applicability without duplicating them.
//!
//! [`string_literal_quote_lengths`] is the companion parser for any
//! rule that needs to scan a string-literal body without its opening
//! and closing delimiters. Currently used only by
//! `unicode_ellipsis_in_panic_messages`'s literal scanner, but it
//! sits here rather than inside that rule because the shape it
//! recognises (plain and raw display strings) is a generic property
//! of Rust string literals, not specific to ellipsis detection.
//!
//! [`take_string_escape`] is the escape-aware front-of-body scanner
//! shared by every rule that walks a *cooked* string literal's body
//! and must tell a real backslash escape (`\n`, `\\`, `\xNN`,
//! `\u{...}`, a line continuation, ...) apart from the bytes around
//! it. `prefer_raw_string` uses it to bail on the first non-eligible
//! escape; `print_macro_split` uses it to locate the `\n` escapes it
//! folds without being fooled by `\\n` (an escaped backslash followed
//! by the letter `n`, which is *not* a newline).
use ;
use Applicability;
use HirId;
use ;
use Span;
/// For each character in `text` that appears in `flagged`, emit a
/// diagnostic against `lint` with the suggested `...` replacement.
///
/// `context_label` is the trailing phrase in the message, e.g.
/// `"comment"` or `` "`panic!` message" ``. `span_for` maps a
/// `(byte_offset_within_text, character_utf8_length)` pair into the
/// [`Span`] of the offending character in source — different callers
/// resolve this differently (a source-file-relative position for the
/// comment scanner, a `BytePos`-arithmetic offset from a literal span
/// for the panic-message scanner).
///
/// Applicability is [`MachineApplicable`] for U+2026 (the rule's
/// primary target, which always maps cleanly to `...`) and
/// [`MaybeIncorrect`] for any user-configured `extra_flagged_chars`
/// entries (whose visual equivalence to `...` is up to the project to
/// assert).
///
/// [`MachineApplicable`]: Applicability::MachineApplicable
/// [`MaybeIncorrect`]: Applicability::MaybeIncorrect
pub
/// Emit a single flagged-character diagnostic at `span`, suggesting
/// the ASCII `...` replacement. Factored out of [`emit_flagged_chars`]
/// so rules that run their own scan loop (the doc-comment scanner,
/// which filters against a code-region mask and a fallible span map)
/// reuse the same message text and applicability.
///
/// Applicability is [`MachineApplicable`] for U+2026 (the rules'
/// primary target, which always maps cleanly to `...`) and
/// [`MaybeIncorrect`] for any user-configured `extra_flagged_chars`
/// entry (whose visual equivalence to `...` is up to the project to
/// assert).
///
/// [`MachineApplicable`]: Applicability::MachineApplicable
/// [`MaybeIncorrect`]: Applicability::MaybeIncorrect
pub
/// HIR-anchored counterpart of [`emit_flagged_char`] for the
/// comment-scanning rules (`unicode_ellipsis_in_comments` and
/// `unicode_ellipsis_in_docs`). They run in a late pass and emit at the
/// comment's enclosing HIR node — resolved by
/// [`crate::enclosing_hir::emit_at_enclosing_hir`] — so a per-item /
/// per-module `#[allow]` / `#[expect]` resolves, not just a crate-root
/// `#![allow]`. The message, suggestion, and applicability match
/// [`emit_flagged_char`] exactly.
pub
/// Diagnostic message for a flagged character, shared by the
/// current-context [`emit_flagged_char`] and HIR-anchored
/// [`emit_flagged_char_hir`] emitters so the two stay identical.
/// Suggestion applicability for a flagged character: `MachineApplicable`
/// for U+2026 (always maps cleanly to `...`), `MaybeIncorrect` for any
/// user-configured `extra_flagged_chars` entry.
/// Return `(prefix_length, suffix_length)` covering the opening and
/// closing delimiters of a Rust string-literal snippet, or `None` if
/// the snippet does not look like a string literal whose body we can
/// scan as plain text.
///
/// Recognises plain (`"..."`) and raw (`r"..."`, `r#"..."#`, ...)
/// strings. Byte / C-string forms are excluded — the helper is for
/// rules that operate on display strings.
pub
/// Take a single backslash escape from the front of a *cooked*
/// string-literal body and return `(escape_text, remainder)`, or
/// `None` if `input` does not start with `\` or the escape is
/// malformed (incomplete `\u{...}` without a closing brace, dangling
/// backslash at end of input, truncated `\xNN`).
///
/// Recognises `\xNN` (4 bytes), `\u{...}` (variable length), and any
/// single-character escape (`\n`, `\t`, `\r`, `\0`, `\"`, `\\`, `\'`,
/// the line-continuation `\<newline>`, ...). The returned slice is the
/// verbatim source spelling of the escape, escapes are not decoded —
/// callers that need the decoded character derive it from the slice.
///
/// The "cooked" qualifier is load-bearing: in a *raw* string literal a
/// backslash is an ordinary character, so running this scanner over a
/// raw body would misread `r"\n"` (literal backslash, literal `n`) as
/// a newline escape. Callers must gate on the literal being cooked
/// before scanning its body with this function.
pub