Skip to content

Commit d8a9cc6

Browse files
committed
fix: fix todo comments identification
1 parent 1ec113d commit d8a9cc6

File tree

5 files changed

+57
-19
lines changed

5 files changed

+57
-19
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ chrono = { version = "0.4.38", features = ["serde"] }
88
clap = { version = "4.5.20", features = ["derive"] }
99
futures = "0.3.31"
1010
indicatif = "0.17.8"
11+
lazy_static = "1.5.0"
1112
open = "5.3.0"
1213
oxc = "0.31.0"
1314
regex = "1.11.0"

src/identify_supported_file.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1+
use lazy_static::lazy_static;
12
use regex::Regex;
23

4+
lazy_static! {
5+
static ref SUPPORTED_FILE_REGEX: Regex =
6+
Regex::new(r"\.[cm]?[jt]sx?$").unwrap();
7+
}
8+
39
pub fn identify_supported_file(file_name: &str) -> bool {
4-
let re = Regex::new(r"\.[cm]?[jt]sx?$").unwrap();
5-
re.is_match(file_name)
10+
SUPPORTED_FILE_REGEX.is_match(file_name)
611
}

src/identify_todo_comment.rs

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
pub const PRIMARY_TODO_KEYWORDS: [&str; 9] = [
2-
"TODO", "FIXME", "CHANGED", "XXX", "HACK", "BUG", "OPTIMIZE", "REFACTOR",
3-
"TEMP",
1+
use lazy_static::lazy_static;
2+
use regex::Regex;
3+
4+
pub const PRIMARY_TODO_KEYWORDS: [&str; 8] = [
5+
"TODO", "FIXME", "XXX", "HACK", "BUG", "OPTIMIZE", "REFACTOR", "TEMP",
46
];
57

6-
pub const SECONDARY_TODO_KEYWORDS: [&str; 13] = [
8+
pub const SECONDARY_TODO_KEYWORDS: [&str; 14] = [
9+
"CHANGED",
710
"IDEA",
811
"NOTE",
912
"REVIEW",
@@ -19,23 +22,33 @@ pub const SECONDARY_TODO_KEYWORDS: [&str; 13] = [
1922
"COMBAK",
2023
];
2124

25+
lazy_static! {
26+
static ref PRIMARY_KEYWORD_REGEXES: Vec<Regex> = PRIMARY_TODO_KEYWORDS
27+
.iter()
28+
.map(|keyword| Regex::new(&format!(
29+
r"(?i)\b{}\b",
30+
regex::escape(keyword)
31+
))
32+
.unwrap())
33+
.collect();
34+
static ref SECONDARY_KEYWORD_REGEX: Regex =
35+
Regex::new(r"(?i)^[^\w]*(\w+)([\s\p{P}]*)(:|[\p{P}\s]|$)").unwrap();
36+
}
37+
2238
pub fn identify_todo_comment(comment_text: &str) -> Option<String> {
2339
let trimmed_text = comment_text.trim();
2440

25-
let words_with_separators: Vec<&str> =
26-
trimmed_text.split_whitespace().collect();
27-
28-
for keyword in PRIMARY_TODO_KEYWORDS.iter() {
29-
for word in &words_with_separators {
30-
if word.to_uppercase().contains(&keyword.to_uppercase()) {
31-
return Some(keyword.to_string());
32-
}
41+
for (i, re) in PRIMARY_KEYWORD_REGEXES.iter().enumerate() {
42+
if re.is_match(trimmed_text) {
43+
return Some(PRIMARY_TODO_KEYWORDS[i].to_string());
3344
}
3445
}
3546

36-
if let Some(first_word) = words_with_separators.first() {
47+
if let Some(captures) = SECONDARY_KEYWORD_REGEX.captures(trimmed_text) {
48+
let first_word = captures.get(1).unwrap().as_str();
49+
3750
for keyword in SECONDARY_TODO_KEYWORDS.iter() {
38-
if first_word.to_uppercase() == keyword.to_uppercase() {
51+
if first_word.eq_ignore_ascii_case(keyword) {
3952
return Some(keyword.to_string());
4053
}
4154
}

tests/identify_todo_comment.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,15 @@ async fn test_primary_keyword_lowercase() {
2525
}
2626

2727
#[tokio::test]
28-
async fn test_secondary_keyword_at_start() {
29-
let comment = "// FIXME: There is a bug.";
30-
assert_eq!(identify_todo_comment(comment), Some("FIXME".to_string()));
28+
async fn test_secondary_keyword_at_start_with_colon() {
29+
let comment = "// NB: There is a nota bene.";
30+
assert_eq!(identify_todo_comment(comment), Some("NB".to_string()));
31+
}
32+
33+
#[tokio::test]
34+
async fn test_secondary_keyword_at_start_with_no_colon() {
35+
let comment = "// DEBUG: There is a debug.";
36+
assert_eq!(identify_todo_comment(comment), Some("DEBUG".to_string()));
3137
}
3238

3339
#[tokio::test]
@@ -71,3 +77,15 @@ async fn test_no_keyword_found() {
7177
let comment = "// This is just a comment without anything.";
7278
assert_eq!(identify_todo_comment(comment), None);
7379
}
80+
81+
#[tokio::test]
82+
async fn test_no_keyword_found_with_similar_primary_word() {
83+
let comment = "// I love todoctor";
84+
assert_eq!(identify_todo_comment(comment), None);
85+
}
86+
87+
#[tokio::test]
88+
async fn test_no_keyword_found_with_similar_secondary_word() {
89+
let comment = "// Dangerous stuff";
90+
assert_eq!(identify_todo_comment(comment), None);
91+
}

0 commit comments

Comments
 (0)