mirror of https://github.com/astral-sh/ruff
Allow shebang comments at start-of-file (#4473)
This commit is contained in:
parent
67c5086aba
commit
3bc29d6c0c
|
|
@ -64,3 +64,11 @@ a = 42 # (One space one NBSP)
|
||||||
#: E262:2:9
|
#: E262:2:9
|
||||||
# (Two spaces) Ok for block comment
|
# (Two spaces) Ok for block comment
|
||||||
a = 42 # (Two spaces)
|
a = 42 # (Two spaces)
|
||||||
|
|
||||||
|
#: E265:5:1
|
||||||
|
### Means test is not done yet
|
||||||
|
# E Means test is giving error (E)
|
||||||
|
# F Means test is failing (F)
|
||||||
|
# EF Means test is giving error and Failing
|
||||||
|
#! Means test is segfaulting
|
||||||
|
# 8 Means test runs forever
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
#
|
||||||
|
#!
|
||||||
|
#:
|
||||||
|
|
@ -67,7 +67,7 @@ pub(crate) fn check_logical_lines(
|
||||||
}
|
}
|
||||||
|
|
||||||
if line.flags().contains(TokenFlags::COMMENT) {
|
if line.flags().contains(TokenFlags::COMMENT) {
|
||||||
whitespace_before_comment(&line, locator, prev_line.is_none(), &mut context);
|
whitespace_before_comment(&line, locator, &mut context);
|
||||||
}
|
}
|
||||||
|
|
||||||
if line.flags().contains(TokenFlags::BRACKET) {
|
if line.flags().contains(TokenFlags::BRACKET) {
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,21 @@ mod tests {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn shebang() -> Result<()> {
|
||||||
|
let diagnostics = test_path(
|
||||||
|
Path::new("pycodestyle/shebang.py"),
|
||||||
|
&settings::Settings::for_rules(vec![
|
||||||
|
Rule::TooFewSpacesBeforeInlineComment,
|
||||||
|
Rule::NoSpaceAfterInlineComment,
|
||||||
|
Rule::NoSpaceAfterBlockComment,
|
||||||
|
Rule::MultipleLeadingHashesForBlockComment,
|
||||||
|
]),
|
||||||
|
)?;
|
||||||
|
assert_messages!(diagnostics);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test_case(false)]
|
#[test_case(false)]
|
||||||
#[test_case(true)]
|
#[test_case(true)]
|
||||||
fn task_tags(ignore_overlong_task_comments: bool) -> Result<()> {
|
fn task_tags(ignore_overlong_task_comments: bool) -> Result<()> {
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,11 @@ pub(crate) struct LogicalLine<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> LogicalLine<'a> {
|
impl<'a> LogicalLine<'a> {
|
||||||
|
/// Returns `true` if this line is positioned at the start of the file.
|
||||||
|
pub(crate) const fn is_start_of_file(&self) -> bool {
|
||||||
|
self.line.tokens_start == 0
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `true` if this is a comment only line
|
/// Returns `true` if this is a comment only line
|
||||||
pub(crate) fn is_comment_only(&self) -> bool {
|
pub(crate) fn is_comment_only(&self) -> bool {
|
||||||
self.flags() == TokenFlags::COMMENT
|
self.flags() == TokenFlags::COMMENT
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,6 @@ impl Violation for MultipleLeadingHashesForBlockComment {
|
||||||
pub(crate) fn whitespace_before_comment(
|
pub(crate) fn whitespace_before_comment(
|
||||||
line: &LogicalLine,
|
line: &LogicalLine,
|
||||||
locator: &Locator,
|
locator: &Locator,
|
||||||
is_first_row: bool,
|
|
||||||
context: &mut LogicalLinesContext,
|
context: &mut LogicalLinesContext,
|
||||||
) {
|
) {
|
||||||
let mut prev_end = TextSize::default();
|
let mut prev_end = TextSize::default();
|
||||||
|
|
@ -149,13 +148,13 @@ pub(crate) fn whitespace_before_comment(
|
||||||
if let TokenKind::Comment = kind {
|
if let TokenKind::Comment = kind {
|
||||||
let range = token.range();
|
let range = token.range();
|
||||||
|
|
||||||
let line = locator.slice(TextRange::new(
|
let line_text = locator.slice(TextRange::new(
|
||||||
locator.line_start(range.start()),
|
locator.line_start(range.start()),
|
||||||
range.start(),
|
range.start(),
|
||||||
));
|
));
|
||||||
let text = locator.slice(range);
|
let token_text = locator.slice(range);
|
||||||
|
|
||||||
let is_inline_comment = !line.trim().is_empty();
|
let is_inline_comment = !line_text.trim().is_empty();
|
||||||
if is_inline_comment {
|
if is_inline_comment {
|
||||||
if range.start() - prev_end < " ".text_len() {
|
if range.start() - prev_end < " ".text_len() {
|
||||||
context.push(
|
context.push(
|
||||||
|
|
@ -166,7 +165,7 @@ pub(crate) fn whitespace_before_comment(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Split into the portion before and after the first space.
|
// Split into the portion before and after the first space.
|
||||||
let mut parts = text.splitn(2, ' ');
|
let mut parts = token_text.splitn(2, ' ');
|
||||||
let symbol = parts.next().unwrap_or("");
|
let symbol = parts.next().unwrap_or("");
|
||||||
let comment = parts.next().unwrap_or("");
|
let comment = parts.next().unwrap_or("");
|
||||||
|
|
||||||
|
|
@ -182,7 +181,7 @@ pub(crate) fn whitespace_before_comment(
|
||||||
context.push(NoSpaceAfterInlineComment, range);
|
context.push(NoSpaceAfterInlineComment, range);
|
||||||
}
|
}
|
||||||
} else if let Some(bad_prefix) = bad_prefix {
|
} else if let Some(bad_prefix) = bad_prefix {
|
||||||
if bad_prefix != '!' || !is_first_row {
|
if bad_prefix != '!' || !line.is_start_of_file() {
|
||||||
if bad_prefix != '#' {
|
if bad_prefix != '#' {
|
||||||
context.push(NoSpaceAfterBlockComment, range);
|
context.push(NoSpaceAfterBlockComment, range);
|
||||||
} else if !comment.is_empty() {
|
} else if !comment.is_empty() {
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,8 @@ E26.py:66:9: E262 Inline comment should start with `# `
|
||||||
67 | # (Two spaces) Ok for block comment
|
67 | # (Two spaces) Ok for block comment
|
||||||
68 | a = 42 # (Two spaces)
|
68 | a = 42 # (Two spaces)
|
||||||
| ^^^^^^^^^^^^^^^ E262
|
| ^^^^^^^^^^^^^^^ E262
|
||||||
|
69 |
|
||||||
|
70 | #: E265:5:1
|
||||||
|
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,4 +40,13 @@ E26.py:32:1: E265 Block comment should start with `# `
|
||||||
35 | pass # an inline comment
|
35 | pass # an inline comment
|
||||||
|
|
|
|
||||||
|
|
||||||
|
E26.py:73:1: E265 Block comment should start with `# `
|
||||||
|
|
|
||||||
|
73 | # F Means test is failing (F)
|
||||||
|
74 | # EF Means test is giving error and Failing
|
||||||
|
75 | #! Means test is segfaulting
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E265
|
||||||
|
76 | # 8 Means test runs forever
|
||||||
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,4 +30,13 @@ E26.py:26:1: E266 Too many leading `#` before block comment
|
||||||
30 | #########################################
|
30 | #########################################
|
||||||
|
|
|
|
||||||
|
|
||||||
|
E26.py:69:1: E266 Too many leading `#` before block comment
|
||||||
|
|
|
||||||
|
69 | #: E265:5:1
|
||||||
|
70 | ### Means test is not done yet
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E266
|
||||||
|
71 | # E Means test is giving error (E)
|
||||||
|
72 | # F Means test is failing (F)
|
||||||
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff/src/rules/pycodestyle/mod.rs
|
||||||
|
---
|
||||||
|
shebang.py:3:1: E265 Block comment should start with `# `
|
||||||
|
|
|
||||||
|
3 | #!/usr/bin/python
|
||||||
|
4 | #
|
||||||
|
5 | #!
|
||||||
|
| ^^ E265
|
||||||
|
6 | #:
|
||||||
|
|
|
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue