-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement whitespace-before-comment (E261, E262, E265, E266) (#2654)
- Loading branch information
1 parent
f5efdd0
commit 824c0d2
Showing
11 changed files
with
394 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
#: E261:1:5 | ||
pass # an inline comment | ||
#: E262:1:12 | ||
x = x + 1 #Increment x | ||
#: E262:1:12 | ||
x = x + 1 # Increment x | ||
#: E262:1:12 | ||
x = y + 1 #: Increment x | ||
#: E265:1:1 | ||
#Block comment | ||
a = 1 | ||
#: E265:2:1 | ||
m = 42 | ||
#! This is important | ||
mx = 42 - 42 | ||
#: E266:3:5 E266:6:5 | ||
def how_it_feel(r): | ||
|
||
### This is a variable ### | ||
a = 42 | ||
|
||
### Of course it is unused | ||
return | ||
#: E265:1:1 E266:2:1 | ||
##if DEBUG: | ||
## logging.error() | ||
#: W291:1:42 | ||
######################################### | ||
#: | ||
|
||
#: Okay | ||
#!/usr/bin/env python | ||
|
||
pass # an inline comment | ||
x = x + 1 # Increment x | ||
y = y + 1 #: Increment x | ||
|
||
# Block comment | ||
a = 1 | ||
|
||
# Block comment1 | ||
|
||
# Block comment2 | ||
aaa = 1 | ||
|
||
|
||
# example of docstring (not parsed) | ||
def oof(): | ||
""" | ||
#foo not parsed | ||
""" | ||
|
||
#################################################################### | ||
# A SEPARATOR # | ||
#################################################################### | ||
|
||
# ################################################################ # | ||
# ####################### another separator ###################### # | ||
# ################################################################ # | ||
#: E262:3:9 | ||
# -*- coding: utf8 -*- | ||
# (One space one NBSP) Ok for block comment | ||
a = 42 # (One space one NBSP) | ||
#: E262:2:9 | ||
# (Two spaces) Ok for block comment | ||
a = 42 # (Two spaces) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
120 changes: 120 additions & 0 deletions
120
crates/ruff/src/rules/pycodestyle/rules/whitespace_before_comment.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
#![allow(dead_code)] | ||
|
||
use rustpython_parser::ast::Location; | ||
use rustpython_parser::lexer::Tok; | ||
|
||
use ruff_macros::{define_violation, derive_message_formats}; | ||
|
||
use crate::ast::types::Range; | ||
use crate::registry::DiagnosticKind; | ||
use crate::source_code::Locator; | ||
use crate::violation::Violation; | ||
|
||
define_violation!( | ||
pub struct TooFewSpacesBeforeInlineComment; | ||
); | ||
impl Violation for TooFewSpacesBeforeInlineComment { | ||
#[derive_message_formats] | ||
fn message(&self) -> String { | ||
format!("Insert at least two spaces before an inline comment") | ||
} | ||
} | ||
|
||
define_violation!( | ||
pub struct NoSpaceAfterInlineComment; | ||
); | ||
impl Violation for NoSpaceAfterInlineComment { | ||
#[derive_message_formats] | ||
fn message(&self) -> String { | ||
format!("Inline comment should start with `# `") | ||
} | ||
} | ||
|
||
define_violation!( | ||
pub struct NoSpaceAfterBlockComment; | ||
); | ||
impl Violation for NoSpaceAfterBlockComment { | ||
#[derive_message_formats] | ||
fn message(&self) -> String { | ||
format!("Block comment should start with `# `") | ||
} | ||
} | ||
|
||
define_violation!( | ||
pub struct MultipleLeadingHashesForBlockComment; | ||
); | ||
impl Violation for MultipleLeadingHashesForBlockComment { | ||
#[derive_message_formats] | ||
fn message(&self) -> String { | ||
format!("Too many leading `#` before block comment") | ||
} | ||
} | ||
|
||
/// E261, E262, E265, E266 | ||
#[cfg(feature = "logical_lines")] | ||
pub fn whitespace_before_comment( | ||
tokens: &[(Location, &Tok, Location)], | ||
locator: &Locator, | ||
) -> Vec<(Range, DiagnosticKind)> { | ||
let mut diagnostics = vec![]; | ||
let mut prev_end = Location::new(0, 0); | ||
for (start, tok, end) in tokens { | ||
if let Tok::Comment(text) = tok { | ||
let line = locator.slice_source_code_range(&Range::new( | ||
Location::new(start.row(), 0), | ||
Location::new(start.row(), start.column()), | ||
)); | ||
|
||
let is_inline_comment = !line.trim().is_empty(); | ||
if is_inline_comment { | ||
if prev_end.row() == start.row() && start.column() < prev_end.column() + 2 { | ||
diagnostics.push(( | ||
Range::new(prev_end, *start), | ||
TooFewSpacesBeforeInlineComment.into(), | ||
)); | ||
} | ||
} | ||
|
||
// Split into the portion before and after the first space. | ||
let mut parts = text.splitn(2, ' '); | ||
let symbol = parts.next().unwrap_or(""); | ||
let comment = parts.next().unwrap_or(""); | ||
|
||
let bad_prefix = if symbol != "#" && symbol != "#:" { | ||
Some(symbol.trim_start_matches('#').chars().next().unwrap_or('#')) | ||
} else { | ||
None | ||
}; | ||
|
||
if is_inline_comment { | ||
if bad_prefix.is_some() || comment.chars().next().map_or(false, char::is_whitespace) | ||
{ | ||
diagnostics.push((Range::new(*start, *end), NoSpaceAfterInlineComment.into())); | ||
} | ||
} else if let Some(bad_prefix) = bad_prefix { | ||
if bad_prefix != '!' || start.row() > 1 { | ||
if bad_prefix != '#' { | ||
diagnostics | ||
.push((Range::new(*start, *end), NoSpaceAfterBlockComment.into())); | ||
} else if !comment.is_empty() { | ||
diagnostics.push(( | ||
Range::new(*start, *end), | ||
MultipleLeadingHashesForBlockComment.into(), | ||
)); | ||
} | ||
} | ||
} | ||
} else if !matches!(tok, Tok::NonLogicalNewline) { | ||
prev_end = *end; | ||
} | ||
} | ||
diagnostics | ||
} | ||
|
||
#[cfg(not(feature = "logical_lines"))] | ||
pub fn whitespace_before_comment( | ||
_tokens: &[(Location, &Tok, Location)], | ||
_locator: &Locator, | ||
) -> Vec<(Range, DiagnosticKind)> { | ||
vec![] | ||
} |
Oops, something went wrong.