Skip to main content

cha_core/
path_shape.rs

1//! Path-shape utility helpers shared across detectors.
2//!
3//! These functions used to live as private duplicated impls inside
4//! `boundary_leak` and `module_envy`. Centralized here so `ProjectQuery`
5//! implementations and standalone helpers stay aligned.
6
7use std::path::Path;
8
9/// True if `path` is under a test directory or named like a test file.
10///
11/// Recognized patterns:
12/// - segment match: `tests/`, `test/`, `__tests__/`, `__mocks__/`,
13///   `spec/`, `specs/`
14/// - filename: starts with `test_` / ends with `_test`, `.test`,
15///   `.spec`, `_spec`
16pub fn is_test_path(path: &Path) -> bool {
17    const TEST_DIRS: &[&str] = &["tests", "test", "__tests__", "__mocks__", "spec", "specs"];
18    let has_test_segment = path.components().any(|c| {
19        c.as_os_str()
20            .to_str()
21            .is_some_and(|s| TEST_DIRS.contains(&s))
22    });
23    if has_test_segment {
24        return true;
25    }
26    if let Some(stem) = path.file_stem().and_then(|s| s.to_str())
27        && (stem.starts_with("test_")
28            || stem.ends_with("_test")
29            || stem.ends_with(".test")
30            || stem.ends_with(".spec")
31            || stem.ends_with("_spec"))
32    {
33        return true;
34    }
35    false
36}