Skip to content

Commit a44d990

Browse files
committed
Add TODO checker
1 parent fb86979 commit a44d990

File tree

3 files changed

+78
-1
lines changed

3 files changed

+78
-1
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ jobs:
8888
- name: Check formatting
8989
run: ./y.sh fmt --check
9090

91+
- name: Check todo
92+
run: ./y.sh check-todo
93+
9194
- name: clippy
9295
run: |
9396
cargo clippy --all-targets -- -D warnings

build_system/src/main.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ mod prepare;
1212
mod rust_tools;
1313
mod rustc_info;
1414
mod test;
15+
mod todo;
1516
mod utils;
1617
const BUILD_DIR: &str = "build";
1718

@@ -45,7 +46,8 @@ Commands:
4546
clone-gcc : Clones the GCC compiler from a specified source.
4647
fmt : Runs rustfmt
4748
fuzz : Fuzzes `cg_gcc` using rustlantis
48-
abi-test : Runs the abi-cafe test suite on the codegen, checking for ABI compatibility with LLVM"
49+
abi-test : Runs the abi-cafe test suite on the codegen, checking for ABI compatibility with LLVM
50+
check-todo : Checks todo in the project"
4951
);
5052
}
5153

@@ -61,6 +63,7 @@ pub enum Command {
6163
Fmt,
6264
Fuzz,
6365
AbiTest,
66+
CheckTodo,
6467
}
6568

6669
fn main() {
@@ -80,6 +83,7 @@ fn main() {
8083
Some("info") => Command::Info,
8184
Some("clone-gcc") => Command::CloneGcc,
8285
Some("abi-test") => Command::AbiTest,
86+
Some("check-todo") => Command::CheckTodo,
8387
Some("fmt") => Command::Fmt,
8488
Some("fuzz") => Command::Fuzz,
8589
Some("--help") => {
@@ -106,6 +110,7 @@ fn main() {
106110
Command::Fmt => fmt::run(),
107111
Command::Fuzz => fuzz::run(),
108112
Command::AbiTest => abi_test::run(),
113+
Command::CheckTodo => todo::run(),
109114
} {
110115
eprintln!("Command failed to run: {e}");
111116
process::exit(1);

build_system/src/todo.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
use std::ffi::OsStr;
2+
use std::fs;
3+
use std::path::{Path, PathBuf};
4+
use std::process::Command;
5+
6+
const EXTENSIONS: &[&str] =
7+
&["rs", "py", "js", "sh", "c", "cpp", "h", "md", "css", "ftl", "toml", "yml", "yaml"];
8+
9+
fn has_supported_extension(path: &Path) -> bool {
10+
path.extension().is_some_and(|ext| EXTENSIONS.iter().any(|e| ext == OsStr::new(e)))
11+
}
12+
13+
fn list_tracked_files() -> Result<Vec<PathBuf>, String> {
14+
let output = Command::new("git")
15+
.args(["ls-files", "-z"])
16+
.output()
17+
.map_err(|e| format!("Failed to run `git ls-files`: {e}"))?;
18+
19+
if !output.status.success() {
20+
let stderr = String::from_utf8_lossy(&output.stderr);
21+
return Err(format!("`git ls-files` failed: {stderr}"));
22+
}
23+
24+
let mut files = Vec::new();
25+
for entry in output.stdout.split(|b| *b == 0) {
26+
if entry.is_empty() {
27+
continue;
28+
}
29+
let path = std::str::from_utf8(entry).unwrap();
30+
files.push(PathBuf::from(path));
31+
}
32+
33+
Ok(files)
34+
}
35+
36+
pub(crate) fn run() -> Result<(), String> {
37+
let files = list_tracked_files()?;
38+
let mut error_count = 0;
39+
// Avoid embedding the task marker in source so greps only find real occurrences.
40+
let todo_marker = "todo".to_ascii_uppercase();
41+
42+
for file in files {
43+
if !has_supported_extension(&file) {
44+
continue;
45+
}
46+
47+
let bytes = fs::read(&file).unwrap();
48+
let contents = std::str::from_utf8(&bytes).unwrap();
49+
50+
for (i, line) in contents.split('\n').enumerate() {
51+
let trimmed = line.trim();
52+
if trimmed.contains(&todo_marker) {
53+
eprintln!(
54+
"{}:{}: {} is used for tasks that should be done before merging a PR; if you want to leave a message in the codebase use FIXME",
55+
file.display(),
56+
i + 1,
57+
todo_marker
58+
);
59+
error_count += 1;
60+
}
61+
}
62+
}
63+
64+
if error_count == 0 {
65+
return Ok(());
66+
}
67+
68+
Err(format!("found {} {}(s)", error_count, todo_marker))
69+
}

0 commit comments

Comments
 (0)