[flake8-todos] Allow words starting with todo (#13640)

Co-authored-by: Micha Reiser <micha@reiser.io>
This commit is contained in:
Sid 2024-10-14 12:21:45 +02:00 committed by GitHub
parent 5caabe54b6
commit 9bb4722ebf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 49 additions and 63 deletions

View file

@ -1,5 +1,6 @@
# TDO006 - accepted # TDO006 - accepted
# TODO (evanrittenhouse): this is a valid TODO # TODO (evanrittenhouse): this is a valid TODO
# Todoism is a word which starts with todo, but is not a todo
# TDO006 - error # TDO006 - error
# ToDo (evanrittenhouse): invalid capitalization # ToDo (evanrittenhouse): invalid capitalization
# todo (evanrittenhouse): another invalid capitalization # todo (evanrittenhouse): another invalid capitalization

View file

@ -287,19 +287,23 @@ impl<'a> TodoDirective<'a> {
pub(crate) fn from_comment(comment: &'a str, comment_range: TextRange) -> Option<Self> { pub(crate) fn from_comment(comment: &'a str, comment_range: TextRange) -> Option<Self> {
// The directive's offset from the start of the comment. // The directive's offset from the start of the comment.
let mut relative_offset = TextSize::new(0); let mut relative_offset = TextSize::new(0);
let mut subset_opt = Some(comment); let mut subset = comment;
// Loop over `#`-delimited sections of the comment to check for directives. This will // Loop over `#`-delimited sections of the comment to check for directives. This will
// correctly handle cases like `# foo # TODO`. // correctly handle cases like `# foo # TODO`.
while let Some(subset) = subset_opt { loop {
let trimmed = subset.trim_start_matches('#').trim_start(); let trimmed = subset.trim_start_matches('#').trim_start();
let offset = subset.text_len() - trimmed.text_len(); let offset = subset.text_len() - trimmed.text_len();
relative_offset += offset; relative_offset += offset;
// Find the first word. Don't use split by whitespace because that would include the `:` character
// in `TODO:`
let first_word = trimmed.split(|c: char| !c.is_alphanumeric()).next()?;
// If we detect a TodoDirectiveKind variant substring in the comment, construct and // If we detect a TodoDirectiveKind variant substring in the comment, construct and
// return the appropriate TodoDirective // return the appropriate TodoDirective
if let Ok(directive_kind) = trimmed.parse::<TodoDirectiveKind>() { if let Ok(directive_kind) = first_word.parse::<TodoDirectiveKind>() {
let len = directive_kind.len(); let len = directive_kind.len();
return Some(Self { return Some(Self {
@ -310,11 +314,11 @@ impl<'a> TodoDirective<'a> {
} }
// Shrink the subset to check for the next phrase starting with "#". // Shrink the subset to check for the next phrase starting with "#".
subset_opt = if let Some(new_offset) = trimmed.find('#') { if let Some(new_offset) = trimmed.find('#') {
relative_offset += TextSize::try_from(new_offset).unwrap(); relative_offset += TextSize::try_from(new_offset).unwrap();
subset.get(relative_offset.to_usize()..) subset = &subset[relative_offset.to_usize()..];
} else { } else {
None break;
}; };
} }
@ -334,30 +338,13 @@ impl FromStr for TodoDirectiveKind {
type Err = (); type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
// The lengths of the respective variant strings: TODO, FIXME, HACK, XXX match s.to_lowercase().as_str() {
for length in [3, 4, 5] { "fixme" => Ok(TodoDirectiveKind::Fixme),
let Some(substr) = s.get(..length) else { "hack" => Ok(TodoDirectiveKind::Hack),
break; "todo" => Ok(TodoDirectiveKind::Todo),
}; "xxx" => Ok(TodoDirectiveKind::Xxx),
_ => Err(()),
match substr.to_lowercase().as_str() {
"fixme" => {
return Ok(TodoDirectiveKind::Fixme);
} }
"hack" => {
return Ok(TodoDirectiveKind::Hack);
}
"todo" => {
return Ok(TodoDirectiveKind::Todo);
}
"xxx" => {
return Ok(TodoDirectiveKind::Xxx);
}
_ => continue,
}
}
Err(())
} }
} }

View file

@ -1,58 +1,56 @@
--- ---
source: crates/ruff_linter/src/rules/flake8_todos/mod.rs source: crates/ruff_linter/src/rules/flake8_todos/mod.rs
--- ---
TD006.py:4:3: TD006 [*] Invalid TODO capitalization: `ToDo` should be `TODO` TD006.py:5:3: TD006 [*] Invalid TODO capitalization: `ToDo` should be `TODO`
| |
2 | # TODO (evanrittenhouse): this is a valid TODO 3 | # Todoism is a word which starts with todo, but is not a todo
3 | # TDO006 - error 4 | # TDO006 - error
4 | # ToDo (evanrittenhouse): invalid capitalization 5 | # ToDo (evanrittenhouse): invalid capitalization
| ^^^^ TD006 | ^^^^ TD006
5 | # todo (evanrittenhouse): another invalid capitalization 6 | # todo (evanrittenhouse): another invalid capitalization
6 | # foo # todo: invalid capitalization 7 | # foo # todo: invalid capitalization
| |
= help: Replace `ToDo` with `TODO` = help: Replace `ToDo` with `TODO`
Safe fix Safe fix
1 1 | # TDO006 - accepted
2 2 | # TODO (evanrittenhouse): this is a valid TODO 2 2 | # TODO (evanrittenhouse): this is a valid TODO
3 3 | # TDO006 - error 3 3 | # Todoism is a word which starts with todo, but is not a todo
4 |-# ToDo (evanrittenhouse): invalid capitalization 4 4 | # TDO006 - error
4 |+# TODO (evanrittenhouse): invalid capitalization 5 |-# ToDo (evanrittenhouse): invalid capitalization
5 5 | # todo (evanrittenhouse): another invalid capitalization 5 |+# TODO (evanrittenhouse): invalid capitalization
6 6 | # foo # todo: invalid capitalization 6 6 | # todo (evanrittenhouse): another invalid capitalization
7 7 | # foo # todo: invalid capitalization
TD006.py:5:3: TD006 [*] Invalid TODO capitalization: `todo` should be `TODO` TD006.py:6:3: TD006 [*] Invalid TODO capitalization: `todo` should be `TODO`
| |
3 | # TDO006 - error 4 | # TDO006 - error
4 | # ToDo (evanrittenhouse): invalid capitalization 5 | # ToDo (evanrittenhouse): invalid capitalization
5 | # todo (evanrittenhouse): another invalid capitalization 6 | # todo (evanrittenhouse): another invalid capitalization
| ^^^^ TD006 | ^^^^ TD006
6 | # foo # todo: invalid capitalization 7 | # foo # todo: invalid capitalization
| |
= help: Replace `todo` with `TODO` = help: Replace `todo` with `TODO`
Safe fix Safe fix
2 2 | # TODO (evanrittenhouse): this is a valid TODO 3 3 | # Todoism is a word which starts with todo, but is not a todo
3 3 | # TDO006 - error 4 4 | # TDO006 - error
4 4 | # ToDo (evanrittenhouse): invalid capitalization 5 5 | # ToDo (evanrittenhouse): invalid capitalization
5 |-# todo (evanrittenhouse): another invalid capitalization 6 |-# todo (evanrittenhouse): another invalid capitalization
5 |+# TODO (evanrittenhouse): another invalid capitalization 6 |+# TODO (evanrittenhouse): another invalid capitalization
6 6 | # foo # todo: invalid capitalization 7 7 | # foo # todo: invalid capitalization
TD006.py:6:9: TD006 [*] Invalid TODO capitalization: `todo` should be `TODO` TD006.py:7:9: TD006 [*] Invalid TODO capitalization: `todo` should be `TODO`
| |
4 | # ToDo (evanrittenhouse): invalid capitalization 5 | # ToDo (evanrittenhouse): invalid capitalization
5 | # todo (evanrittenhouse): another invalid capitalization 6 | # todo (evanrittenhouse): another invalid capitalization
6 | # foo # todo: invalid capitalization 7 | # foo # todo: invalid capitalization
| ^^^^ TD006 | ^^^^ TD006
| |
= help: Replace `todo` with `TODO` = help: Replace `todo` with `TODO`
Safe fix Safe fix
3 3 | # TDO006 - error 4 4 | # TDO006 - error
4 4 | # ToDo (evanrittenhouse): invalid capitalization 5 5 | # ToDo (evanrittenhouse): invalid capitalization
5 5 | # todo (evanrittenhouse): another invalid capitalization 6 6 | # todo (evanrittenhouse): another invalid capitalization
6 |-# foo # todo: invalid capitalization 7 |-# foo # todo: invalid capitalization
6 |+# foo # TODO: invalid capitalization 7 |+# foo # TODO: invalid capitalization