# LineGuard Technical Architecture
## Overview
LineGuard follows a modular architecture with clear separation of concerns, making it easy to test, maintain, and extend.
## Core Components
### 1. CLI Module (`cli.rs`)
- **Responsibility**: Command-line argument parsing and validation
- **Key Features**:
- Uses `clap` crate for argument parsing
- Validates input parameters
- Handles help and version display
- **Interfaces**:
- `parse_args() -> CliArgs`
- `validate_args(args: &CliArgs) -> Result<(), Error>`
### 2. File Discovery Module (`discovery.rs`)
- **Responsibility**: Finding files to check based on input patterns
- **Key Features**:
- Glob pattern expansion
- Recursive directory traversal
- Stdin file list processing
- Ignore pattern filtering
- **Interfaces**:
- `discover_files(args: &CliArgs) -> Result<Vec<PathBuf>, Error>`
- `should_check_file(path: &Path, config: &Config) -> bool`
### 3. Checker Module (`checker.rs`)
- **Responsibility**: Core lint checking logic
- **Key Features**:
- Newline ending validation
- Trailing space detection
- Parallel file processing
- Streaming support for large files (>10MB)
- Permission error handling
- **Interfaces**:
- `check_file(path: &Path, config: &Config) -> CheckResult`
- `check_file_streaming(path: &Path, config: &Config) -> CheckResult`
- `check_newline_ending(content: &str) -> Option<Issue>`
- `check_trailing_spaces(content: &str) -> Vec<Issue>`
### 4. Reporter Module (`reporter.rs`)
- **Responsibility**: Formatting and outputting results
- **Key Features**:
- Multiple output formats (human, JSON, GitHub)
- Colored output support
- Progress indication
- **Interfaces**:
- `trait Reporter { fn report(&self, results: &[CheckResult]); }`
- `create_reporter(format: OutputFormat) -> Box<dyn Reporter>`
### 5. Configuration Module (`config.rs`)
- **Responsibility**: Loading and managing configuration
- **Key Features**:
- Config file parsing (`.lineguardrc`)
- Default configuration
- Auto-discovery in parent directories
- CLI override support
- **Interfaces**:
- `load_config(path: Option<&Path>) -> Result<Config, Error>`
- `find_config_file() -> Option<PathBuf>`
- `Config::default() -> Config`
### 6. Fixer Module (`fixer.rs`)
- **Responsibility**: Automatically fixing detected issues
- **Key Features**:
- Fix trailing spaces
- Fix newline endings
- Dry-run mode support
- Streaming support for large files
- **Interfaces**:
- `fix_file(path: &Path, issues: &[Issue], config: &Config, dry_run: bool) -> Result<FixResult, Error>`
- `fix_file_streaming(path: &Path, issues: &[Issue], config: &Config, dry_run: bool) -> Result<FixResult, Error>`
### 7. Git Module (`git.rs`)
- **Responsibility**: Git repository operations and commit range filtering
- **Key Features**:
- Detect if current directory is a Git repository
- Validate commit hashes
- Get list of files changed between commits
- Support for commit ranges (from..to)
- **Interfaces**:
- `is_git_repository(path: &Path) -> Result<bool>`
- `get_changed_files(from: &str, to: Option<&str>, repo_path: &Path) -> Result<Vec<PathBuf>>`
## Data Structures
### Core Types
```rust
pub struct CliArgs {
pub files: Vec<String>,
pub stdin: bool,
pub recursive: bool,
pub format: OutputFormat,
pub quiet: bool,
pub verbose: bool,
pub no_color: bool,
pub config: Option<PathBuf>,
pub ignore: Vec<String>,
pub extensions: Option<Vec<String>>,
pub no_newline_check: bool,
pub no_trailing_space: bool,
pub fix: bool,
pub dry_run: bool,
pub from: Option<String>,
pub to: Option<String>,
}
pub struct Config {
pub checks: CheckConfig,
pub ignore_patterns: Vec<String>,
pub file_extensions: Vec<String>,
}
pub struct CheckConfig {
pub newline_ending: bool,
pub trailing_spaces: bool,
}
pub struct CheckResult {
pub file_path: PathBuf,
pub issues: Vec<Issue>,
pub error: Option<String>,
}
pub struct FixResult {
pub file_path: PathBuf,
pub fixed: bool,
pub issues_fixed: Vec<Issue>,
}
pub struct Issue {
pub issue_type: IssueType,
pub line: Option<usize>,
pub message: String,
}
pub enum IssueType {
MissingNewline,
MultipleNewlines,
TrailingSpace,
}
pub enum OutputFormat {
Human,
Json,
GitHub,
}
```
## Dependencies
### External Crates
- `clap` (v4) - Command-line argument parsing
- `glob` - File pattern matching
- `serde` / `serde_json` - JSON serialization
- `colored` - Terminal color output
- `rayon` - Parallel processing
- `anyhow` - Error handling
- `thiserror` - Error type definitions
- `indicatif` - Progress bars
- `toml` - Configuration file parsing
### Testing Dependencies
- `assert_cmd` - CLI testing
- `predicates` - Test assertions
- `tempfile` - Temporary test files
## Error Handling
### Error Types
```rust
#[derive(Debug, thiserror::Error)]
pub enum LineGuardError {
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Pattern error: {0}")]
Pattern(#[from] glob::PatternError),
#[error("Configuration error: {0}")]
Config(String),
#[error("No files found matching pattern")]
NoFilesFound,
#[error("Permission denied: {0}")]
PermissionDenied(String),
}
```
## Performance Considerations
### Parallel Processing
- Use `rayon` for parallel file checking
- Configurable thread pool size
- Batch processing for small files
### Memory Efficiency
- Stream large files line-by-line
- Avoid loading entire file content when possible
- Use `BufReader` for file operations
### Optimization Strategies
- Skip binary file detection
- Cache compiled regex patterns
- Early exit on first issue (when appropriate)
## Testing Strategy
### Unit Tests
- Each module has corresponding test module
- Test individual functions in isolation
- Mock file system operations where needed
### Integration Tests
- Test CLI with actual file operations
- Test different output formats
- Test error scenarios
### Test Organization
```
tests/
├── cli_tests.rs # CLI argument handling
├── checker_tests.rs # Core checking logic
├── reporter_tests.rs # Output formatting
├── integration_tests.rs # End-to-end scenarios
├── fix_tests.rs # Auto-fix functionality
├── config_file_tests.rs # Configuration loading
├── permission_tests.rs # Permission error handling
├── large_file_tests.rs # Streaming for large files
├── check_options_tests.rs # CLI check flags
├── git_range_tests.rs # Git commit range filtering
└── ... # Other feature-specific tests
```
## Build Configuration
### Cargo.toml Structure
```toml
[package]
name = "lineguard"
version = "0.1.0"
edition = "2024"
license = "Apache-2.0"
repository = "https://github.com/hydai/lineguard"
[dependencies]
# Listed above
[dev-dependencies]
# Testing dependencies
[profile.release]
lto = true
codegen-units = 1
opt-level = 3
```
## Module Dependency Graph
```
main.rs
├── cli.rs
├── config.rs
├── discovery.rs
│ ├── config.rs
│ └── git.rs
├── checker.rs
│ └── config.rs
├── fixer.rs
│ ├── checker.rs (for types)
│ └── config.rs
├── reporter.rs
│ └── checker.rs (for types)
└── git.rs
```