1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
// Per-language metric and AST modules deliberately consume the macro-
// generated tree-sitter token enums via `use crate::*` and `use Foo::*`
// inside match expressions — explicit imports would list dozens of
// variants per arm and obscure the per-language token sets that are the
// point of these files. Allowed at the module level rather than per
// function so the per-language impl blocks stay readable.
// Per-language Cargo features (commit 7e96b466) let a downstream build
// only a subset of grammars. In such a build the code for the disabled
// languages — their macro-generated `*Code` / `*Parser` tags plus the
// getter / checker / metric helpers and shared plumbing only those
// languages reach — is compiled but never constructed, so `-D dead-code`
// fires on ~180 items that are all live in the default `all-languages`
// build. Relax dead-code to a warning only when the full language set is
// NOT enabled; the default build and `--all-features` (and thus the
// primary CI gate and `make pre-commit`) still hard-deny it, so genuine
// dead code is caught there. Fixes the long-red `features
// (no-default-features / minimal-langs (lib))` CI legs.
//! big-code-analysis is a library to analyze and extract information
//! from source codes written in many different programming languages.
//!
//! You can find the source code of this software on
//! <a href="https://github.com/dekobon/big-code-analysis/" target="_blank">GitHub</a>,
//! while issues and feature requests can be posted on the respective
//! <a href="https://github.com/dekobon/big-code-analysis/issues/" target="_blank">GitHub Issue Tracker</a>.
//!
//! ## Quick start
//!
//! Most callers want the recommended entry points exposed in
//! [`prelude`]:
//!
//! ```no_run
//! use big_code_analysis::prelude::*;
//!
//! let source = b"fn main() {}";
//! let space = analyze(
//! Source::new(LANG::Rust, source),
//! MetricsOptions::default(),
//! ).expect("Rust source parses");
//! println!("cognitive sum: {}", space.metrics.cognitive.cognitive_sum());
//! ```
//!
//! ## Supported Languages
//!
//! Each grammar is gated behind a per-language Cargo feature; the
//! default `all-languages` feature enables every grammar so the
//! historical "every language compiled in" behaviour is preserved.
//! Library consumers that only need a subset can opt out of the
//! defaults — see [Per-language Cargo features][feat] in the book.
//!
//! - Bash (`bash`)
//! - C (`c`, upstream `tree-sitter-c`; owns `.c`)
//! - C/C++ (`cpp`, upstream `tree-sitter-cpp`; the default for `.cpp` /
//! `.cc` / `.h` and also exposes the internal `ccomment` / `preproc`
//! C-family helpers)
//! - C++, Firefox-internal "Mozcpp" (`mozcpp`, opt-in; owns no file
//! extensions — select it by name)
//! - C# (`csharp`)
//! - Objective-C (`objc`, upstream `tree-sitter-objc`; owns `.m`; `.mm`
//! Objective-C++ stays on C/C++)
//! - Elixir (`elixir`)
//! - Go (`go`)
//! - Groovy (`groovy`)
//! - F5 iRules (`irules`)
//! - Java (`java`)
//! - JavaScript (`javascript`)
//! - JavaScript, Firefox-internal "MozJS" (`mozjs`)
//! - Kotlin (`kotlin`)
//! - Lua (`lua`)
//! - Perl (`perl`)
//! - PHP (`php`)
//! - Python (`python`)
//! - Ruby (`ruby`)
//! - Rust (`rust`)
//! - Tcl (`tcl`)
//! - TSX (`tsx`)
//! - TypeScript (`typescript`)
//!
//! [feat]: https://dekobon.github.io/big-code-analysis/library/cargo-features.html
//!
//! ## Supported Metrics
//!
//! - ABC: it measures the size of a source code based on
//! assignments, branches, and conditions.
//! - CC: it calculates the code complexity examining the control flow of a
//! program. Both standard and modified flavours are exposed: the
//! modified variant collapses all case/match arms inside a single
//! switch/match/when/select into one decision point.
//! - Cognitive Complexity: it measures how difficult it is
//! to understand a unit of code.
//! - SLOC: it counts the number of lines in a source file.
//! - PLOC: it counts the number of physical lines (instructions)
//! contained in a source file.
//! - LLOC: it counts the number of logical lines (statements)
//! contained in a source file.
//! - CLOC: it counts the number of comments in a source file.
//! - BLANK: it counts the number of blank lines in a source file.
//! - HALSTEAD: it is a suite that provides a series of information,
//! such as the effort required to maintain the analyzed code,
//! the size in bits to store the program, the difficulty to understand
//! the code, an estimate of the number of bugs present in the codebase,
//! and an estimate of the time needed to implement the software.
//! - MI: it is a suite that allows to evaluate the maintainability
//! of a software.
//! - NOM: it counts the number of functions and closures
//! in a file/trait/class.
//! - NEXITS: it counts the number of possible exit points
//! from a method/function.
//! - NARGS: it counts the number of arguments of a function/method.
//! - NPA: it counts the number of public attributes of a class.
//! - NPM: it counts the number of public methods of a class.
//! - WMC: it is the sum of the complexities of all methods
//! in a class.
// Internal-only modules. Nothing is re-exported from these.
// `langs` hosts the `mk_langs!` macro expansion. `LANG` is the only
// public name; the per-language `<Lang>Code` tags and `<Lang>Parser`
// aliases are `pub(crate)` parser machinery reached only through the
// [`Ast`] seam.
pub use crate;
// `<Lang>Code` tags are reached crate-internally through `use crate::*`
// in the per-language `Checker` / `Getter` / `Alterator` / metric impls.
pub use crate;
// The `<Lang>Parser` aliases are the concrete `Parser<<Lang>Code>` types
// driven by the `AstInner` dispatch in `crate::langs`; at the crate root
// they are reached only from `#[cfg(test)]` modules, so the re-export is
// `unused` in a non-test build.
pub use crate;
// `ParseLangError` is the `FromStr` error for `LANG`; it is defined in
// the `mk_lang!` macro layer (`crate::macros`) rather than `crate::langs`.
pub use crateParseLangError;
// Internal crate-root re-exports. Hand-written per-language modules
// (`src/getter.rs`, `src/checker.rs`, `src/alterator.rs`, the
// per-language metric impls) use `use crate::*` to bring the
// macro-generated `<Lang>Code` token enums and per-language helper
// types into scope; the per-language token enums in
// `src/languages/language_*.rs` are also reached through the crate
// root. Re-exporting these as `pub(crate)` keeps internal compilation
// working without widening the published surface.
pub use crate*;
pub use crate*;
// Hand-written modules (`src/spaces.rs`, `src/output/dump_metrics.rs`,
// the metric macros) refer to per-metric submodules by their short
// crate-root path (`crate::abc`, `crate::cognitive`, ...). Re-export
// them under those names without widening the public surface.
pub use crate;
// Module declarations. Each `pub use` line below names exactly the
// items intended to be part of the public API surface; anything not
// listed stays out of the crate root. Per issue #255, glob re-exports
// (`pub use module::*`) are no longer used here because every newly
// `pub`-marked helper in any sub-module would silently leak into the
// published API.
// --- Core analysis entry points and result types (spaces.rs) ---
pub use crate;
// `metrics_inner` is the per-`ParserTrait` metric walk core consumed by
// feature-gated arms in `mk_action!` (`AstInner::run_metrics`). With
// `--no-default-features` and no language feature, every arm compiles
// out and the re-export becomes nominally unused; the language-features
// that ship in the default set keep the symbol live in any normal build.
pub use cratemetrics_inner;
pub use cratecheck_func_space;
/// Per-metric implementations.
///
/// Each sub-module owns one metric — its `Stats` accumulator, the
/// per-language trait implementations, and any small helpers used
/// only by tests. Most callers will not need these directly; reach
/// through [`CodeMetrics`] on a [`FuncSpace`] instead.
/// Plain, `Deserialize`-capable data-transfer structs mirroring the
/// serialized metric wire shape. The compute types' `Serialize` impls
/// delegate here, making these the single definition of the JSON / YAML /
/// TOML / CBOR output format and the canonical way to read `bca` output
/// back (`serde_json::from_str::<wire::FuncSpace>(…)`).
// --- Change-history (VCS) metrics ---
//
// The project's first language-agnostic, non-AST metric family
// (issue #328). Gated behind the `vcs-git` backend feature (the
// `vcs` umbrella turns it on); the generic surface is backend-neutral
// so future backends (#335) reuse it unchanged.
/// Change-history (VCS) metrics derived from version-control history:
/// churn, commit frequency, author count / ownership dilution, bug- and
/// security-fix history, and an ordinal composite risk score. See
/// [`vcs::build_history_index`].
// --- Errors ---
pub use crate;
// --- Metric selection ---
pub use crate;
// --- Suppression markers ---
pub use crate;
/// Canonical metric catalog: offender sub-metric ids with their
/// long-form sentences and [`metric_catalog::Direction`], plus the
/// family view rendered by `bca list-metrics`. Single source of truth
/// shared by the library's offender formatters and the CLI's threshold
/// engine, which pins its extractor ids to [`metric_catalog::METRICS`]
/// via a parity test.
/// Output formatters: CSV, SARIF, Checkstyle, clang/MSVC warning
/// lines, and AST/metric pretty-dumps used by `bca` and the offender
/// reporters.
///
/// The most commonly used writers (`write_csv`, `write_sarif`,
/// `write_checkstyle`, `write_clang_warning`, `write_code_climate`,
/// `write_msvc_warning`) and shared types (`OffenderRecord`,
/// `Severity`, `TOOL_ID`, `CSV_HEADER`, `CSV_EXTENSION`) are also
/// re-exported at the crate root.
pub use crate;
// --- AST plumbing (Node) ---
pub use crateNode;
// --- Language detection / I/O helpers ---
pub use crate;
// --- Source walker ---
pub use crate;
// --- Comment removal ---
//
// `rm_comments` is the internal walk core reached only through the
// [`Ast::strip_comments`] seam (`AstInner::run_strip_comments`).
// --- Per-file node counting / finding (reached via the `Ast` seam) ---
pub use crate;
pub use crate;
// --- AST dump ---
pub use crate;
// --- Halstead operator/operand result type ---
pub use crateOps;
// `ops_inner` is the explicit-name walk core consumed by feature-gated
// `mk_action!` arms (`AstInner::run_ops`); mirrors the `metrics_inner`
// re-export above and is nominally unused under `--no-default-features`.
pub use crateops_inner;
// --- Preprocessor handling (C/C++) ---
pub use crate;
// --- Alterator trait (per-language AST simplification) ---
//
// Crate-internal: an extension trait over the `pub(crate)` `Checker`
// machinery, used only by the per-language `Parser<T>` impls behind the
// [`Ast`] seam.
pub use crateAlterator;
// --- Generic parser plumbing (crate-internal) ---
//
// `Parser`, `ParserTrait`, `Filter`, and `LanguageInfo` are the
// internal parser machinery driving every metric walk. They are
// `pub(crate)` only: the single public analysis seam is [`Ast`],
// which wraps the language-dispatched `AstInner` carrier. See
// STABILITY.md.
pub use crateParser;
pub use crate;
/// Re-export of the underlying `tree-sitter` crate.
///
/// Lets callers build a [`tree_sitter::Tree`] (via
/// [`tree_sitter::Parser`]) against the exact grammar version this
/// library is pinned to, and feed it back through
/// [`Ast::from_tree_sitter`] without taking a separate `tree-sitter`
/// dependency that may drift out of pin.
///
/// This is part of the value-not-stable surface: the underlying
/// pin may bump in any minor release (see `STABILITY.md`). The inner
/// node of a [`Node`] is reached the same way, through
/// [`Node::as_tree_sitter`], and carries the same value-not-stable
/// caveat.
pub use tree_sitter;
/// The version of this `big-code-analysis` library crate.
///
/// Sourced from the crate's own `CARGO_PKG_VERSION` at compile time.
/// Exposed so downstream surfaces (the REST `/v1/version` endpoint, the
/// Python `__version__` attribute, …) can report the exact library
/// version they were built against without re-deriving it from Cargo
/// metadata.
pub const VERSION: &str = env!;
/// Recommended entry points for the 90% case.
///
/// Star-import this module to get the curated set of types and
/// functions most callers need:
///
/// ```no_run
/// use big_code_analysis::prelude::*;
///
/// let source = b"fn main() {}";
/// let space = analyze(
/// Source::new(LANG::Rust, source),
/// MetricsOptions::default(),
/// ).expect("Rust source parses");
/// # let _ = space;
/// ```
///
/// Anything not exposed here can still be imported with its
/// fully-qualified name from the crate root (`use
/// big_code_analysis::Something;`). Items deliberately omitted from
/// the prelude are either deprecated, doc-hidden, or unlikely to
/// appear in typical caller code.