Repository navigation
Library
The echoes crate runs the same scan as the command line and returns the report as data.
[dependencies]
echoes = { version = "0.9", default-features = false, features = ["std"] }The default cli feature only adds the cargo echoes binary. Library users need std, which reads the workspace through cargo metadata and loads .echoes.toml.
let report = echoes::Echoes::default()
.functions()
.context_blocks()
.run(".")
.unwrap();
println!("{}", echoes::human(&report, false));let report = echoes::Echoes::default()
.context_dependency_depth(2)
.context_dependencies(echoes::DependencySearch {
check_latest: Some(false),
..echoes::DependencySearch::default()
})
.run(".")
.unwrap();
if let Some(reuse) = &report.reuse {
println!("{}", reuse.coverage.packages);
}let report = echoes::Echoes::default()
.functions()
.run_organization("my-org")
.unwrap();
if let Some(organization) = &report.organization {
println!("{}", organization.coverage.complete);
}The examples use the main branch API.
Most settings have an Echoes builder method. Pass dependency options together with context_dependencies(DependencySearch { ... }), which overrides only populated fields. context_dependency_depth sets depth alone, and context_select and context_search take a ContextScope. Unset settings fall back to .echoes.toml and then defaults. run_selected(&organizations, &repositories) scans GitHub organizations or users together with named repositories instead of a workspace, either list may be empty, and repository_owner(".") returns the owner the command line uses when --organization has no name.
Report holds the totals and the groups.
| Field | Holds |
|---|---|
groups |
Doctest groups, then function groups, each Group with its sites, the copy to keep first |
context_groups |
Context matches, each ContextGroup with source ranges and no copy to keep |
total, unique
|
Doctests scanned and their distinct forms |
functions, unique_functions
|
Functions scanned and their distinct forms |
context_blocks, unique_context_blocks
|
Contexts scanned and their distinct forms |
reuse |
Some when a dependency search ran, the ReuseReport of candidate groups and their coverage |
organization |
Some for an organization scan, the OrganizationReport of repositories, packages, file provenance and coverage |
A function Group also carries a Remedy, explained on the Checks page.
Report.reuse is Some when dependency depth is positive. Each ReuseGroup pairs one selected local context with its candidates, whose depth records shortest dependency distance and whose action identifies the reuse path to review. Matches require human compatibility review. reuse.coverage.complete is false when requested analysis is incomplete, with details in failures. See Dependency reuse and Performance.
human, json and annotations render the report as text, JSON and GitHub workflow commands. exit_code returns 2 for incomplete dependency or organization coverage, 1 for gated findings and 0 otherwise. Its no_fail argument suppresses only 1. See Organization search for the organization fields.
The comparison lives in syn-canon, which works on any syn::File and runs in no_std with alloc. Use it to compare code echoes never sees, such as generated snippets.
[dependencies]
syn = { version = "3", features = ["full"] }
syn-canon = "0.4"let form = |source: &str| syn_canon::canonicalize(syn::parse_str(source).unwrap());
assert_eq!(
form("fn area(width: u32, height: u32) -> u32 { width * height }"),
form("fn product(a: u32, b: u32) -> u32 { return a * b; }"),
);canonicalize_failing builds the form for code meant to fail to compile, as in a compile_fail doctest, and keeps every spelling that matters for the failure. contexts emits the form of every function body, block, match arm and closure in a file. Equal forms compare equal and hash equally, and the key stays stable within one major version of syn-canon.