diff --git a/crates/ruff/resources/test/fixtures/flake8_todos/TD002.py b/crates/ruff/resources/test/fixtures/flake8_todos/TD002.py index 3c4867516f..438d6a1e6a 100644 --- a/crates/ruff/resources/test/fixtures/flake8_todos/TD002.py +++ b/crates/ruff/resources/test/fixtures/flake8_todos/TD002.py @@ -1,6 +1,12 @@ # T002 - accepted # TODO (evanrittenhouse): this has an author -# TODO(evanrittenhouse): this also has an author +# TODO(evanrittenhouse): this has an author +# TODO (evanrittenhouse) and more: this has an author +# TODO(evanrittenhouse) and more: this has an author +# TODO@mayrholu: this has an author +# TODO @mayrholu: this has an author +# TODO@mayrholu and more: this has an author +# TODO @mayrholu and more: this has an author # T002 - errors # TODO: this has no author # FIXME: neither does this diff --git a/crates/ruff/src/rules/flake8_todos/rules/todos.rs b/crates/ruff/src/rules/flake8_todos/rules/todos.rs index ce6c1ee9fa..20072b0ded 100644 --- a/crates/ruff/src/rules/flake8_todos/rules/todos.rs +++ b/crates/ruff/src/rules/flake8_todos/rules/todos.rs @@ -67,7 +67,7 @@ pub struct MissingTodoAuthor; impl Violation for MissingTodoAuthor { #[derive_message_formats] fn message(&self) -> String { - format!("Missing author in TODO; try: `# TODO(): ...`") + format!("Missing author in TODO; try: `# TODO(): ...` or `# TODO @: ...`") } } @@ -229,7 +229,7 @@ static ISSUE_LINK_REGEX_SET: Lazy = Lazy::new(|| { RegexSet::new([ r#"^#\s*(http|https)://.*"#, // issue link r#"^#\s*\d+$"#, // issue code - like "003" - r#"^#\s*[A-Z]{1,6}\-?\d+$"#, // issue code - like "TD003" or "TD-003" + r#"^#\s*[A-Z]{1,6}\-?\d+$"#, // issue code - like "TD003" ]) .unwrap() }); @@ -339,8 +339,7 @@ fn directive_errors( } } -/// Checks for "static" errors in the comment: missing colon, missing author, etc. This function -/// modifies `diagnostics` in-place. +/// Checks for "static" errors in the comment: missing colon, missing author, etc. fn static_errors( diagnostics: &mut Vec, comment: &str, @@ -358,6 +357,15 @@ fn static_errors( } else { trimmed.text_len() } + } else if trimmed.starts_with('@') { + if let Some(end_index) = trimmed.find(|c: char| c.is_whitespace() || c == ':') { + TextSize::try_from(end_index).unwrap() + } else { + // TD002 + diagnostics.push(Diagnostic::new(MissingTodoAuthor, directive.range)); + + TextSize::new(0) + } } else { // TD002 diagnostics.push(Diagnostic::new(MissingTodoAuthor, directive.range)); diff --git a/crates/ruff/src/rules/flake8_todos/snapshots/ruff__rules__flake8_todos__tests__missing-todo-author_TD002.py.snap b/crates/ruff/src/rules/flake8_todos/snapshots/ruff__rules__flake8_todos__tests__missing-todo-author_TD002.py.snap index 0647b705d4..f14a00cd5f 100644 --- a/crates/ruff/src/rules/flake8_todos/snapshots/ruff__rules__flake8_todos__tests__missing-todo-author_TD002.py.snap +++ b/crates/ruff/src/rules/flake8_todos/snapshots/ruff__rules__flake8_todos__tests__missing-todo-author_TD002.py.snap @@ -1,41 +1,41 @@ --- source: crates/ruff/src/rules/flake8_todos/mod.rs --- -TD002.py:5:3: TD002 Missing author in TODO; try: `# TODO(): ...` - | -3 | # TODO(evanrittenhouse): this also has an author -4 | # T002 - errors -5 | # TODO: this has no author - | ^^^^ TD002 -6 | # FIXME: neither does this -7 | # TODO : and neither does this - | +TD002.py:11:3: TD002 Missing author in TODO; try: `# TODO(): ...` or `# TODO @: ...` + | + 9 | # TODO @mayrholu and more: this has an author +10 | # T002 - errors +11 | # TODO: this has no author + | ^^^^ TD002 +12 | # FIXME: neither does this +13 | # TODO : and neither does this + | -TD002.py:6:3: TD002 Missing author in TODO; try: `# TODO(): ...` - | -4 | # T002 - errors -5 | # TODO: this has no author -6 | # FIXME: neither does this - | ^^^^^ TD002 -7 | # TODO : and neither does this -8 | # foo # TODO: this doesn't either - | +TD002.py:12:3: TD002 Missing author in TODO; try: `# TODO(): ...` or `# TODO @: ...` + | +10 | # T002 - errors +11 | # TODO: this has no author +12 | # FIXME: neither does this + | ^^^^^ TD002 +13 | # TODO : and neither does this +14 | # foo # TODO: this doesn't either + | -TD002.py:7:3: TD002 Missing author in TODO; try: `# TODO(): ...` - | -5 | # TODO: this has no author -6 | # FIXME: neither does this -7 | # TODO : and neither does this - | ^^^^ TD002 -8 | # foo # TODO: this doesn't either - | +TD002.py:13:3: TD002 Missing author in TODO; try: `# TODO(): ...` or `# TODO @: ...` + | +11 | # TODO: this has no author +12 | # FIXME: neither does this +13 | # TODO : and neither does this + | ^^^^ TD002 +14 | # foo # TODO: this doesn't either + | -TD002.py:8:9: TD002 Missing author in TODO; try: `# TODO(): ...` - | -6 | # FIXME: neither does this -7 | # TODO : and neither does this -8 | # foo # TODO: this doesn't either - | ^^^^ TD002 - | +TD002.py:14:9: TD002 Missing author in TODO; try: `# TODO(): ...` or `# TODO @: ...` + | +12 | # FIXME: neither does this +13 | # TODO : and neither does this +14 | # foo # TODO: this doesn't either + | ^^^^ TD002 + |