From eeadcac53372fbc7baf165805e46df76c63cff77 Mon Sep 17 00:00:00 2001 From: Dhruv Manilawala Date: Wed, 13 Sep 2023 09:16:37 +0530 Subject: [PATCH] Detect `noqa` directives for multi-line f-strings --- crates/ruff/src/directives.rs | 65 +++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/crates/ruff/src/directives.rs b/crates/ruff/src/directives.rs index af41fbac0981e0..22d858e18ed8fc 100644 --- a/crates/ruff/src/directives.rs +++ b/crates/ruff/src/directives.rs @@ -95,6 +95,27 @@ fn extract_noqa_line_for(lxr: &[LexResult], locator: &Locator, indexer: &Indexer break; } + // F-strings can be multi-line even without triple quotes. For example, + // + // ```python + // f"foo { + // x + // * + // y + // }" + // ``` + // + // We expect `noqa` directives on the last line of the f-string. + Tok::FStringEnd => { + // SAFETY: If we're at the end of a f-string, the indexer must have a + // corresponding f-string range for it. + let f_string_start = indexer.f_string_range(range.start()).unwrap().start(); + string_mappings.push(TextRange::new( + locator.line_start(f_string_start), + range.end(), + )); + } + // For multi-line strings, we expect `noqa` directives on the last line of the // string. Tok::String { @@ -429,6 +450,50 @@ ghi NoqaMapping::from_iter([TextRange::new(TextSize::from(6), TextSize::from(28))]) ); + let contents = "x = f'abc { +a + * + b +}' +y = 2 +"; + assert_eq!( + noqa_mappings(contents), + NoqaMapping::from_iter([TextRange::new(TextSize::from(0), TextSize::from(32))]) + ); + + let contents = "x = f'''abc +def +ghi +''' +y = 2 +z = x + 1"; + assert_eq!( + noqa_mappings(contents), + NoqaMapping::from_iter([TextRange::new(TextSize::from(0), TextSize::from(23))]) + ); + + let contents = "x = 1 +y = f'''abc +def +ghi +''' +z = 2"; + assert_eq!( + noqa_mappings(contents), + NoqaMapping::from_iter([TextRange::new(TextSize::from(6), TextSize::from(29))]) + ); + + let contents = "x = 1 +y = f'''abc +def +ghi +'''"; + assert_eq!( + noqa_mappings(contents), + NoqaMapping::from_iter([TextRange::new(TextSize::from(6), TextSize::from(29))]) + ); + let contents = r"x = \ 1"; assert_eq!(