From 3314ea699b1dbdfd690167bbc0dc069e5ade1ce5 Mon Sep 17 00:00:00 2001 From: Long Ho Date: Thu, 30 Jul 2026 18:34:09 -0400 Subject: [PATCH] fix: reject unmatched entry globs --- crates/codescythe/analyze/discovery.rs | 10 ++++++++++ crates/codescythe/analyze/tests.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/crates/codescythe/analyze/discovery.rs b/crates/codescythe/analyze/discovery.rs index 5d82eba..dc987ae 100644 --- a/crates/codescythe/analyze/discovery.rs +++ b/crates/codescythe/analyze/discovery.rs @@ -64,6 +64,16 @@ pub(super) fn discover_entry_files( } let entry_globs = build_glob_set(&config.entry)?; + for pattern in config.entry.iter().filter(|pattern| has_glob_meta(pattern)) { + let entry_glob = build_glob_set(std::slice::from_ref(pattern))?; + if !project_files + .iter() + .any(|file| entry_glob.is_match(relative_path(cwd, file))) + { + anyhow::bail!("entry glob {pattern:?} matched no files in the configured project"); + } + } + let mut entries = BTreeSet::::new(); for pattern in &config.entry { if !has_glob_meta(pattern) { diff --git a/crates/codescythe/analyze/tests.rs b/crates/codescythe/analyze/tests.rs index cc5464d..9f2f561 100644 --- a/crates/codescythe/analyze/tests.rs +++ b/crates/codescythe/analyze/tests.rs @@ -16,6 +16,32 @@ fn finds_unused_exports_and_files_in_knip_style_fixture() { assert!(!analysis.issues.exports.contains_key("index.ts")); } +#[test] +fn rejects_an_entry_glob_that_matches_no_project_files() { + let tempdir = tempfile::tempdir().unwrap(); + let cwd = tempdir.path(); + write_file( + cwd, + "codescythe.json", + r#"{ + "entry": ["src/*.entry.ts", "src/missing/**/*.ts"], + "project": "src/**/*.ts" + }"#, + ); + write_file(cwd, "src/main.entry.ts", "console.log('entry');\n"); + + let config = crate::load_config(cwd, None).unwrap(); + let error = analyze_path(cwd, &config, AnalysisOptions::default()).unwrap_err(); + let message = format!("{error:#}"); + + assert!( + message.contains( + r#"entry glob "src/missing/**/*.ts" matched no files in the configured project"# + ), + "{message}" + ); +} + #[test] fn expect_error_suppresses_an_expected_unused_file() { let analysis = analyze_inline_project(&[