rustloclib/lib.rs
1//! # rustloclib
2//!
3//! A Rust-aware lines of code counter library with a simple, flat data model.
4//!
5//! ## Overview
6//!
7//! Unlike generic LOC counters (tokei, cloc, scc), this library understands Rust's
8//! unique structure where tests live alongside production code. It uses AST-aware
9//! parsing to categorize lines into one of 6 types:
10//!
11//! - **code**: Production code logic lines (in src/, not in test blocks)
12//! - **tests**: Test code logic lines (#[test], #[cfg(test)], tests/)
13//! - **examples**: Example code logic lines (examples/)
14//! - **docs**: Documentation comments (///, //!, /** */, /*! */)
15//! - **comments**: Regular comments (//, /* */)
16//! - **blanks**: Blank/whitespace-only lines
17//!
18//! The key insight: only actual code lines need context (code/tests/examples).
19//! A blank is a blank, a comment is a comment - where they appear doesn't matter.
20//!
21//! ## Data Pipeline
22//!
23//! The library is organized into four stages that form a clear data pipeline:
24//!
25//! ```text
26//! ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
27//! │ source │ -> │ data │ -> │ query │ -> │ output │
28//! └──────────┘ └──────────┘ └──────────┘ └──────────┘
29//! Discover Parse & Filter, Format
30//! files collect sort strings
31//! ```
32//!
33//! ### Stage 1: Source Discovery ([`source`])
34//!
35//! Find what files to analyze:
36//! - [`WorkspaceInfo`]: Discover Cargo workspace structure
37//! - [`FilterConfig`]: Include/exclude files with glob patterns
38//!
39//! ### Stage 2: Data Collection ([`data`])
40//!
41//! Parse files and collect statistics:
42//! - [`gather_stats`]: Parse a single file into [`Locs`]
43//! - [`count_workspace`]: Count all files, returns [`CountResult`]
44//! - [`diff_commits`]: Compare commits, returns [`DiffResult`]
45//!
46//! ### Stage 3: Query Processing ([`query`])
47//!
48//! Filter, aggregate, and sort the collected data:
49//! - [`CountQuerySet`]: Processed count data ready for display
50//! - [`LineTypes`]: Which line types to include
51//! - [`Ordering`]: How to sort results
52//!
53//! ### Stage 4: Output Formatting ([`output`])
54//!
55//! Format data for presentation:
56//! - [`LOCTable`]: Table with headers, rows, footer (all strings)
57//!
58//! ## Example
59//!
60//! ```rust
61//! use rustloclib::{count_file, count_workspace, CountOptions, FilterConfig};
62//! use std::fs;
63//! use tempfile::tempdir;
64//!
65//! // Set up a temporary project
66//! let dir = tempdir().unwrap();
67//! fs::write(dir.path().join("Cargo.toml"), r#"
68//! [package]
69//! name = "my-lib"
70//! version = "0.1.0"
71//! edition = "2021"
72//! "#).unwrap();
73//! fs::create_dir(dir.path().join("src")).unwrap();
74//! let file_path = dir.path().join("src/lib.rs");
75//! fs::write(&file_path, "pub fn hello() {\n println!(\"Hi\");\n}\n").unwrap();
76//!
77//! // Count a single file
78//! let stats = count_file(&file_path).unwrap();
79//! assert_eq!(stats.code, 3); // 3 lines of production code
80//!
81//! // Count an entire workspace
82//! let result = count_workspace(dir.path(), CountOptions::new()).unwrap();
83//! assert!(result.total.code >= 1);
84//!
85//! // Count with filtering
86//! let filter = FilterConfig::new().exclude("**/generated/**").unwrap();
87//! let result = count_workspace(dir.path(), CountOptions::new().filter(filter)).unwrap();
88//! ```
89//!
90//! ## Full Pipeline Example
91//!
92//! ```rust,ignore
93//! use rustloclib::{
94//! count_workspace, CountOptions, CountQuerySet, LOCTable,
95//! Aggregation, LineTypes, Ordering,
96//! };
97//!
98//! // Stage 1-2: Discover and collect
99//! let result = count_workspace(".", CountOptions::new())?;
100//!
101//! // Stage 3: Query (filter, aggregate, sort)
102//! let queryset = CountQuerySet::from_result(
103//! &result,
104//! Aggregation::ByCrate,
105//! LineTypes::everything(),
106//! Ordering::by_code(),
107//! );
108//!
109//! // Stage 4: Format for output
110//! let table = LOCTable::from_count_queryset(&queryset);
111//! ```
112//!
113//! ## Origins
114//!
115//! The parsing logic is adapted from [cargo-warloc](https://github.com/Maximkaaa/cargo-warloc)
116//! by Maxim Gritsenko. We thank the original author for the excellent parsing implementation.
117//! cargo-warloc is MIT licensed.
118
119// Pipeline modules (in order)
120pub mod data;
121pub mod output;
122pub mod query;
123pub mod source;
124
125// Infrastructure
126pub mod error;
127
128// Re-export all public types at crate root for convenience
129pub use data::{
130 count_directory, count_file, count_workspace, diff_commits, diff_workdir, gather_stats,
131 gather_stats_for_path, CountOptions, CountResult, CrateDiffStats, CrateStats, DiffOptions,
132 DiffResult, FileChangeType, FileDiffStats, FileStats, Locs, LocsDiff, ModuleStats,
133 VisitorContext, WorkdirDiffMode,
134};
135pub use error::RustlocError;
136pub use output::{LOCTable, TableRow};
137pub use query::{
138 Aggregation, CountQuerySet, DiffQuerySet, LineTypes, OrderBy, OrderDirection, Ordering,
139 QueryItem,
140};
141pub use source::{CrateInfo, FilterConfig, WorkspaceInfo};
142
143/// Result type for rustloclib operations
144pub type Result<T> = std::result::Result<T, RustlocError>;