Skip to content

Commit

Permalink
Allow shebang comments at start-of-file
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed May 17, 2023
1 parent 67c5086 commit a9d00e1
Show file tree
Hide file tree
Showing 10 changed files with 71 additions and 7 deletions.
8 changes: 8 additions & 0 deletions crates/ruff/resources/test/fixtures/pycodestyle/E26.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,11 @@ def oof():
#: E262:2:9
# (Two spaces) Ok for block comment
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
4 changes: 4 additions & 0 deletions crates/ruff/resources/test/fixtures/pycodestyle/shebang.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/python
#
#!
#:
2 changes: 1 addition & 1 deletion crates/ruff/src/checkers/logical_lines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ pub(crate) fn check_logical_lines(
}

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) {
Expand Down
15 changes: 15 additions & 0 deletions crates/ruff/src/rules/pycodestyle/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,21 @@ mod tests {
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(true)]
fn task_tags(ignore_overlong_task_comments: bool) -> Result<()> {
Expand Down
5 changes: 5 additions & 0 deletions crates/ruff/src/rules/pycodestyle/rules/logical_lines/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@ pub(crate) struct 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
pub(crate) fn is_comment_only(&self) -> bool {
self.flags() == TokenFlags::COMMENT
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ impl Violation for MultipleLeadingHashesForBlockComment {
pub(crate) fn whitespace_before_comment(
line: &LogicalLine,
locator: &Locator,
is_first_row: bool,
context: &mut LogicalLinesContext,
) {
let mut prev_end = TextSize::default();
Expand All @@ -149,13 +148,13 @@ pub(crate) fn whitespace_before_comment(
if let TokenKind::Comment = kind {
let range = token.range();

let line = locator.slice(TextRange::new(
let line_text = locator.slice(TextRange::new(
locator.line_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 range.start() - prev_end < " ".text_len() {
context.push(
Expand All @@ -166,7 +165,7 @@ pub(crate) fn whitespace_before_comment(
}

// 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 comment = parts.next().unwrap_or("");

Expand All @@ -182,7 +181,7 @@ pub(crate) fn whitespace_before_comment(
context.push(NoSpaceAfterInlineComment, range);
}
} 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 != '#' {
context.push(NoSpaceAfterBlockComment, range);
} else if !comment.is_empty() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ E26.py:66:9: E262 Inline comment should start with `# `
67 | # (Two spaces) Ok for block comment
68 | a = 42 # (Two spaces)
| ^^^^^^^^^^^^^^^ E262
69 |
70 | #: E265:5:1
|


Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,13 @@ E26.py:32:1: E265 Block comment should start with `# `
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
|


Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,13 @@ E26.py:26:1: E266 Too many leading `#` before block comment
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)
|


Original file line number Diff line number Diff line change
@@ -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 | #:
|


0 comments on commit a9d00e1

Please sign in to comment.