mirror of https://github.com/astral-sh/ruff
Extend pragma comment cases (#7687)
## Summary Extends the pragma comment detection in the formatter to support case-insensitive `noqa` (as supposed by Ruff), plus a variety of other pragmas (`isort:`, `nosec`, etc.). Also extracts the detection out into the trivia crate so that we can reuse it in the linter (see: https://github.com/astral-sh/ruff/issues/7471). ## Test Plan `cargo test`
This commit is contained in:
parent
46b85ab0a9
commit
f62b4c801f
|
|
@ -1,5 +1,6 @@
|
|||
# Pragma reserved width fixtures
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # noqa: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # NoQA: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # type: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # pyright: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # pylint: This shouldn't break
|
||||
|
|
@ -9,6 +10,7 @@ i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # nocover
|
|||
|
||||
# Pragma fixtures for non-breaking space (lead by NBSP)
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # noqa: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # NoQA: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # type: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # pyright: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # pylint: This shouldn't break
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@ use std::borrow::Cow;
|
|||
use ruff_formatter::{format_args, write, FormatError, FormatOptions, SourceCode};
|
||||
use ruff_python_ast::node::{AnyNodeRef, AstNode};
|
||||
use ruff_python_ast::PySourceType;
|
||||
use ruff_python_trivia::{lines_after, lines_after_ignoring_trivia, lines_before};
|
||||
use ruff_python_trivia::{
|
||||
is_pragma_comment, lines_after, lines_after_ignoring_trivia, lines_before,
|
||||
};
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange};
|
||||
|
||||
use crate::comments::{CommentLinePosition, SourceComment};
|
||||
|
|
@ -370,17 +372,8 @@ impl Format<PyFormatContext<'_>> for FormatTrailingEndOfLineComment<'_> {
|
|||
|
||||
let normalized_comment = normalize_comment(self.comment, source)?;
|
||||
|
||||
// Trim the normalized comment to detect excluded pragmas (strips NBSP).
|
||||
let trimmed = strip_comment_prefix(&normalized_comment)?.trim_start();
|
||||
|
||||
let is_pragma = if let Some((maybe_pragma, _)) = trimmed.split_once(':') {
|
||||
matches!(maybe_pragma, "noqa" | "type" | "pyright" | "pylint")
|
||||
} else {
|
||||
trimmed.starts_with("noqa")
|
||||
};
|
||||
|
||||
// Don't reserve width for excluded pragma comments.
|
||||
let reserved_width = if is_pragma {
|
||||
let reserved_width = if is_pragma_comment(&normalized_comment) {
|
||||
0
|
||||
} else {
|
||||
// Start with 2 because of the two leading spaces.
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/trailing_c
|
|||
```py
|
||||
# Pragma reserved width fixtures
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # noqa: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # NoQA: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # type: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # pyright: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # pylint: This shouldn't break
|
||||
|
|
@ -15,6 +16,7 @@ i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # nocover
|
|||
|
||||
# Pragma fixtures for non-breaking space (lead by NBSP)
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # noqa: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # NoQA: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # type: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # pyright: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # pylint: This shouldn't break
|
||||
|
|
@ -39,6 +41,7 @@ i = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
|||
```py
|
||||
# Pragma reserved width fixtures
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # noqa: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # NoQA: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # type: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # pyright: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # pylint: This shouldn't break
|
||||
|
|
@ -50,6 +53,7 @@ i = (
|
|||
|
||||
# Pragma fixtures for non-breaking space (lead by NBSP)
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # noqa: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # NoQA: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # type: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # pyright: This shouldn't break
|
||||
i = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",) # pylint: This shouldn't break
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
mod comment_ranges;
|
||||
mod cursor;
|
||||
mod pragmas;
|
||||
pub mod textwrap;
|
||||
mod tokenizer;
|
||||
mod whitespace;
|
||||
|
||||
pub use comment_ranges::CommentRanges;
|
||||
pub use cursor::*;
|
||||
pub use pragmas::*;
|
||||
pub use tokenizer::*;
|
||||
pub use whitespace::*;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
/// Returns `true` if a comment appears to be a pragma comment.
|
||||
///
|
||||
/// ```
|
||||
/// assert!(ruff_python_trivia::is_pragma_comment("# type: ignore"));
|
||||
/// assert!(ruff_python_trivia::is_pragma_comment("# noqa: F401"));
|
||||
/// assert!(ruff_python_trivia::is_pragma_comment("# noqa"));
|
||||
/// assert!(ruff_python_trivia::is_pragma_comment("# NoQA"));
|
||||
/// assert!(ruff_python_trivia::is_pragma_comment("# nosec"));
|
||||
/// assert!(ruff_python_trivia::is_pragma_comment("# nosec B602, B607"));
|
||||
/// assert!(ruff_python_trivia::is_pragma_comment("# isort: off"));
|
||||
/// assert!(ruff_python_trivia::is_pragma_comment("# isort: skip"));
|
||||
/// ```
|
||||
pub fn is_pragma_comment(comment: &str) -> bool {
|
||||
let Some(content) = comment.strip_prefix('#') else {
|
||||
return false;
|
||||
};
|
||||
let trimmed = content.trim_start();
|
||||
|
||||
// Case-insensitive match against `noqa` (which doesn't require a trailing colon).
|
||||
matches!(
|
||||
trimmed.as_bytes(),
|
||||
[b'n' | b'N', b'o' | b'O', b'q' | b'Q', b'a' | b'A', ..]
|
||||
) ||
|
||||
// Case-insensitive match against pragmas that don't require a trailing colon.
|
||||
trimmed.starts_with("nosec") ||
|
||||
// Case-sensitive match against a variety of pragmas that _do_ require a trailing colon.
|
||||
trimmed
|
||||
.split_once(':')
|
||||
.is_some_and(|(maybe_pragma, _)| matches!(maybe_pragma, "isort" | "type" | "pyright" | "pylint" | "flake8" | "ruff"))
|
||||
}
|
||||
Loading…
Reference in New Issue