MCPcopy Index your code
hub / github.com/RustPython/RustPython / check_fstring_literal

Method check_fstring_literal

crates/vm/src/vm/compile.rs:225–258  ·  view source on GitHub ↗

Check an f-string literal element for invalid escapes. The range covers content only (no prefix/quotes). Also handles `\{` / `\}` at the literal–interpolation boundary, equivalent to `_PyTokenizer_warn_invalid_escape_sequence` handling `FSTRING_MIDDLE` / `FSTRING_END` tokens.

(&self, range: TextRange)

Source from the content-addressed store, hash-verified

223 /// equivalent to `_PyTokenizer_warn_invalid_escape_sequence` handling
224 /// `FSTRING_MIDDLE` / `FSTRING_END` tokens.
225 fn check_fstring_literal(&self, range: TextRange) {
226 let start = range.start().to_usize();
227 let end = range.end().to_usize();
228 if start >= end || end > self.source.len() {
229 return;
230 }
231 if let Some((ch, offset)) = first_invalid_escape(self.source, start, end, false) {
232 warn_invalid_escape_sequence(self.source, ch, offset, self.filename, self.vm);
233 return;
234 }
235 // In CPython, _PyTokenizer_warn_invalid_escape_sequence handles
236 // `\{` and `\}` for FSTRING_MIDDLE/FSTRING_END tokens. Ruff
237 // splits the literal element before the interpolation delimiter,
238 // so the `\` sits at the end of the literal range and the `{`/`}`
239 // sits just after it. Only warn when the number of trailing
240 // backslashes is odd (an even count means they are all escaped).
241 let trailing_bs = self.source.as_bytes()[start..end]
242 .iter()
243 .rev()
244 .take_while(|&&b| b == b'\\')
245 .count();
246 if trailing_bs % 2 == 1
247 && let Some(&after) = self.source.as_bytes().get(end)
248 && (after == b'{' || after == b'}')
249 {
250 warn_invalid_escape_sequence(
251 self.source,
252 after as char,
253 end - 1,
254 self.filename,
255 self.vm,
256 );
257 }
258 }
259
260 /// Visit f-string elements, checking literals and recursing into
261 /// interpolation expressions and format specs.

Callers 1

Calls 11

first_invalid_escapeFunction · 0.85
to_usizeMethod · 0.45
startMethod · 0.45
endMethod · 0.45
lenMethod · 0.45
countMethod · 0.45
revMethod · 0.45
iterMethod · 0.45
as_bytesMethod · 0.45
getMethod · 0.45

Tested by

no test coverage detected