Skip to content

Commit d2656e8

Browse files
[flake8-todos] Allow VSCode GitHub PR extension style links in missing-todo-link (TD003) (#15519)
## Summary Allow links to issues that appear on the same line as the TODO directive, if they conform to the format that VSCode's GitHub PR extension produces. Revival of #9627 (the branch was stale enough that rebasing was a lot harder than just making the changes anew). Credit should go to the author of that PR though. Closes #8061 Co-authored-by: Martin Bernstorff <[email protected]>
1 parent c53ee60 commit d2656e8

File tree

3 files changed

+49
-12
lines changed

3 files changed

+49
-12
lines changed

crates/ruff_linter/resources/test/fixtures/flake8_todos/TD003.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,10 @@ def foo(x):
3434

3535
# foo # TODO: no link!
3636

37+
# TODO: https://github.com/astral-sh/ruff/pull/9627 A todo with a link on the same line
38+
39+
# TODO: #9627 A todo with a number on the same line
40+
41+
# TODO: A todo with a random number, 5431
42+
3743
# TODO: here's a TODO on the last line with no link

crates/ruff_linter/src/rules/flake8_todos/rules/todos.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ impl Violation for MissingTodoAuthor {
9191
/// # TODO(charlie): this comment has a 3-digit issue code
9292
/// # 003
9393
///
94+
/// # TODO(charlie): https://github.com/astral-sh/ruff/issues/3870
95+
/// # this comment has an issue link
96+
///
97+
/// # TODO(charlie): #003 this comment has a 3-digit issue code
98+
/// # with leading character `#`
99+
///
94100
/// # TODO(charlie): this comment has an issue code (matches the regex `[A-Z]+\-?\d+`)
95101
/// # SIXCHR-003
96102
/// ```
@@ -100,7 +106,7 @@ pub(crate) struct MissingTodoLink;
100106
impl Violation for MissingTodoLink {
101107
#[derive_message_formats]
102108
fn message(&self) -> String {
103-
"Missing issue link on the line following this TODO".to_string()
109+
"Missing issue link for this TODO".to_string()
104110
}
105111
}
106112

@@ -224,7 +230,7 @@ impl Violation for MissingSpaceAfterTodoColon {
224230
}
225231
}
226232

227-
static ISSUE_LINK_REGEX_SET: LazyLock<RegexSet> = LazyLock::new(|| {
233+
static ISSUE_LINK_OWN_LINE_REGEX_SET: LazyLock<RegexSet> = LazyLock::new(|| {
228234
RegexSet::new([
229235
r"^#\s*(http|https)://.*", // issue link
230236
r"^#\s*\d+$", // issue code - like "003"
@@ -233,6 +239,14 @@ static ISSUE_LINK_REGEX_SET: LazyLock<RegexSet> = LazyLock::new(|| {
233239
.unwrap()
234240
});
235241

242+
static ISSUE_LINK_TODO_LINE_REGEX_SET: LazyLock<RegexSet> = LazyLock::new(|| {
243+
RegexSet::new([
244+
r"\s*(http|https)://.*", // issue link
245+
r"\s*#\d+.*", // issue code - like "#003"
246+
])
247+
.unwrap()
248+
});
249+
236250
pub(crate) fn todos(
237251
diagnostics: &mut Vec<Diagnostic>,
238252
todo_comments: &[TodoComment],
@@ -257,6 +271,13 @@ pub(crate) fn todos(
257271
static_errors(diagnostics, content, range, directive);
258272

259273
let mut has_issue_link = false;
274+
// VSCode recommended links on same line are ok:
275+
// `# TODO(dylan): #1234`
276+
if ISSUE_LINK_TODO_LINE_REGEX_SET
277+
.is_match(locator.slice(TextRange::new(directive.range.end(), range.end())))
278+
{
279+
continue;
280+
}
260281
let mut curr_range = range;
261282
for next_range in comment_ranges.iter().skip(range_index + 1).copied() {
262283
// Ensure that next_comment_range is in the same multiline comment "block" as
@@ -274,7 +295,7 @@ pub(crate) fn todos(
274295
break;
275296
}
276297

277-
if ISSUE_LINK_REGEX_SET.is_match(next_comment) {
298+
if ISSUE_LINK_OWN_LINE_REGEX_SET.is_match(next_comment) {
278299
has_issue_link = true;
279300
}
280301

Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
---
22
source: crates/ruff_linter/src/rules/flake8_todos/mod.rs
33
---
4-
TD003.py:15:3: TD003 Missing issue link on the line following this TODO
4+
TD003.py:15:3: TD003 Missing issue link for this TODO
55
|
66
14 | # TDO003 - errors
77
15 | # TODO: this comment has no
88
| ^^^^ TD003
99
16 | # link after it
1010
|
1111

12-
TD003.py:18:3: TD003 Missing issue link on the line following this TODO
12+
TD003.py:18:3: TD003 Missing issue link for this TODO
1313
|
1414
16 | # link after it
1515
17 |
@@ -19,7 +19,7 @@ TD003.py:18:3: TD003 Missing issue link on the line following this TODO
1919
20 | return x
2020
|
2121

22-
TD003.py:31:3: TD003 Missing issue link on the line following this TODO
22+
TD003.py:31:3: TD003 Missing issue link for this TODO
2323
|
2424
29 | # TDO-3870
2525
30 |
@@ -29,20 +29,30 @@ TD003.py:31:3: TD003 Missing issue link on the line following this TODO
2929
33 | # TDO-3870
3030
|
3131

32-
TD003.py:35:9: TD003 Missing issue link on the line following this TODO
32+
TD003.py:35:9: TD003 Missing issue link for this TODO
3333
|
3434
33 | # TDO-3870
3535
34 |
3636
35 | # foo # TODO: no link!
3737
| ^^^^ TD003
3838
36 |
39-
37 | # TODO: here's a TODO on the last line with no link
39+
37 | # TODO: https://github.com/astral-sh/ruff/pull/9627 A todo with a link on the same line
4040
|
4141

42-
TD003.py:37:3: TD003 Missing issue link on the line following this TODO
42+
TD003.py:41:3: TD003 Missing issue link for this TODO
4343
|
44-
35 | # foo # TODO: no link!
45-
36 |
46-
37 | # TODO: here's a TODO on the last line with no link
44+
39 | # TODO: #9627 A todo with a number on the same line
45+
40 |
46+
41 | # TODO: A todo with a random number, 5431
47+
| ^^^^ TD003
48+
42 |
49+
43 | # TODO: here's a TODO on the last line with no link
50+
|
51+
52+
TD003.py:43:3: TD003 Missing issue link for this TODO
53+
|
54+
41 | # TODO: A todo with a random number, 5431
55+
42 |
56+
43 | # TODO: here's a TODO on the last line with no link
4757
| ^^^^ TD003
4858
|

0 commit comments

Comments
 (0)