evault_core/traits/scanner.rs
1//! [`CodeScanner`] — find references to environment variables in source code.
2
3use std::path::{Path, PathBuf};
4
5use crate::error::ScannerError;
6
7/// Where a scanner found a variable reference.
8#[derive(Debug, Clone, PartialEq, Eq, Hash)]
9pub struct ScanHit {
10 /// File the reference was found in.
11 pub path: PathBuf,
12 /// 1-based line number of the reference.
13 ///
14 /// Lines are split on `\n` and `\r\n`. Files that use only bare `\r`
15 /// line endings (legacy Mac OS Classic) are treated as a single line;
16 /// implementations should document this in their own docs if relevant.
17 pub line: usize,
18 /// 1-based **character** column where the reference begins (Unicode
19 /// scalar values, not bytes). Editors universally count columns in
20 /// characters, so a hit at column `N` lands where a user clicking
21 /// `goto N` would expect, even if the line contains multi-byte UTF-8
22 /// before the match.
23 pub column: usize,
24 /// Variable name as it appears in the code (e.g. `DATABASE_URL`).
25 pub name: String,
26}
27
28/// Walk a directory tree looking for references to environment variables.
29///
30/// Implementations should:
31/// - skip common build/output directories (`target`, `node_modules`, `dist`, …);
32/// - skip binary files (no UTF-8) without error;
33/// - return one [`ScanHit`] per reference (a variable referenced N times in
34/// one file produces N hits).
35pub trait CodeScanner: Send + Sync {
36 /// Scan the directory rooted at `root` and return all hits.
37 ///
38 /// # Errors
39 /// Returns [`ScannerError::Io`] if the file system cannot be walked;
40 /// [`ScannerError::Pattern`] if the configured patterns are invalid.
41 fn scan(&self, root: &Path) -> Result<Vec<ScanHit>, ScannerError>;
42}