pub(crate) fn apply_entry_pivot(
report: rinkaku_core::render::Report,
path: &str,
) -> rinkaku_core::render::Report {
let graph = rinkaku_core::graph::pivot_graph(&report.graph, path);
rinkaku_core::render::Report { graph, ..report }
}
pub(crate) fn entry_pivot_empty_note(
report: &rinkaku_core::render::Report,
path: &str,
) -> Option<String> {
if report.graph.nodes.is_empty() {
return None;
}
if report.graph.roots.is_empty() {
Some(format!("note: no symbols under {path}"))
} else {
None
}
}
pub(crate) fn garbage_input_note(
diff_text: &str,
report: &rinkaku_core::render::Report,
) -> Option<&'static str> {
if diff_text.trim().is_empty() {
return None;
}
if !report.files.is_empty() || !report.skipped.is_empty() || !report.tests.is_empty() {
return None;
}
Some("note: no file changes recognized in input; expected a unified diff")
}
pub(crate) fn repo_outline_empty_note(
report: &rinkaku_core::render::Report,
) -> Option<&'static str> {
if !report.files.is_empty() || !report.removed.is_empty() {
return None;
}
Some("note: no supported source files found in the repository")
}
#[cfg(test)]
mod tests {
use super::*;
mod garbage_input_note_tests {
use super::*;
use pretty_assertions::assert_eq;
use rinkaku_core::render::Report;
fn empty_graph() -> rinkaku_core::graph::SymbolGraph {
rinkaku_core::graph::SymbolGraph {
nodes: vec![],
edges: vec![],
roots: vec![],
}
}
fn empty_report() -> Report {
Report {
origin: rinkaku_core::render::ReportOrigin::Diff,
files: vec![],
skipped: vec![],
graph: empty_graph(),
tests: vec![],
fan_ins: vec![],
file_size_warnings: vec![],
file_size_bands: vec![],
removed: vec![],
}
}
fn non_empty_report() -> Report {
Report {
origin: rinkaku_core::render::ReportOrigin::Diff,
files: vec![rinkaku_core::render::FileReport {
path: "src/lib.rs".to_string(),
symbols: vec![],
}],
skipped: vec![],
graph: empty_graph(),
tests: vec![],
fan_ins: vec![],
file_size_warnings: vec![],
file_size_bands: vec![],
removed: vec![],
}
}
#[test]
fn should_return_note_when_input_is_non_empty_but_report_has_no_entries() {
let actual = garbage_input_note("this is not a diff at all\n", &empty_report());
assert_eq!(
Some("note: no file changes recognized in input; expected a unified diff"),
actual
);
}
#[test]
fn should_return_none_when_input_is_empty() {
let actual = garbage_input_note("", &empty_report());
assert_eq!(None, actual);
}
#[test]
fn should_return_none_when_input_is_whitespace_only() {
let actual = garbage_input_note(" \n\n ", &empty_report());
assert_eq!(None, actual);
}
#[test]
fn should_return_none_when_report_has_file_entries() {
let actual = garbage_input_note("some diff text", &non_empty_report());
assert_eq!(None, actual);
}
#[test]
fn should_return_none_when_report_has_only_skipped_entries() {
let report = Report {
origin: rinkaku_core::render::ReportOrigin::Diff,
files: vec![],
skipped: vec![rinkaku_core::render::SkippedFile {
path: "assets/logo.png".to_string(),
reason: rinkaku_core::render::SkipReason::Binary,
}],
graph: empty_graph(),
tests: vec![],
fan_ins: vec![],
file_size_warnings: vec![],
file_size_bands: vec![],
removed: vec![],
};
let actual = garbage_input_note("some diff text", &report);
assert_eq!(None, actual);
}
#[test]
fn should_return_none_when_report_has_only_test_summary_entries() {
let report = Report {
origin: rinkaku_core::render::ReportOrigin::Diff,
files: vec![],
skipped: vec![],
graph: empty_graph(),
tests: vec![rinkaku_core::render::TestFileSummary {
path: "src/lib.rs".to_string(),
symbol_count: 1,
}],
fan_ins: vec![],
file_size_warnings: vec![],
file_size_bands: vec![],
removed: vec![],
};
let actual = garbage_input_note("some diff text", &report);
assert_eq!(None, actual);
}
#[test]
fn should_return_none_when_report_has_only_generated_skip_entries() {
let report = Report {
origin: rinkaku_core::render::ReportOrigin::Diff,
files: vec![],
skipped: vec![
rinkaku_core::render::SkippedFile {
path: "Cargo.lock".to_string(),
reason: rinkaku_core::render::SkipReason::Generated,
},
rinkaku_core::render::SkippedFile {
path: "vendor/generated.go".to_string(),
reason: rinkaku_core::render::SkipReason::Generated,
},
],
graph: empty_graph(),
tests: vec![],
fan_ins: vec![],
file_size_warnings: vec![],
file_size_bands: vec![],
removed: vec![],
};
let actual = garbage_input_note("some diff text", &report);
assert_eq!(None, actual);
}
}
mod apply_entry_pivot_tests {
use super::*;
use pretty_assertions::assert_eq;
use rinkaku_core::diff::LineRange;
use rinkaku_core::extract::{ExtractedSymbol, SymbolKind};
use rinkaku_core::render::{FileReport, Report};
fn symbol(name: &str, referenced_names: Vec<&str>) -> ExtractedSymbol {
ExtractedSymbol {
id: String::new(),
name: name.to_string(),
kind: SymbolKind::Function,
signature: format!("fn {name}()"),
range: LineRange { start: 1, end: 1 },
container: None,
referenced_names: referenced_names.into_iter().map(str::to_string).collect(),
dependencies: vec![],
omitted_dependency_matches: 0,
is_test: false,
classification: None,
previous_signature: None,
}
}
fn report_with_api_and_util() -> Report {
let files = vec![
FileReport {
path: "src/api/handler.rs".to_string(),
symbols: vec![symbol("api", vec!["helper"])],
},
FileReport {
path: "src/util.rs".to_string(),
symbols: vec![symbol("helper", vec![])],
},
];
let graph = rinkaku_core::graph::build_graph(&files);
Report {
origin: rinkaku_core::render::ReportOrigin::Diff,
files,
skipped: vec![],
graph,
tests: vec![],
fan_ins: vec![],
file_size_warnings: vec![],
file_size_bands: vec![],
removed: vec![],
}
}
#[test]
fn should_re_root_graph_at_prefix_while_leaving_other_fields_untouched() {
let report = report_with_api_and_util();
let actual = apply_entry_pivot(report.clone(), "src/api");
let expected = Report {
graph: rinkaku_core::graph::pivot_graph(&report.graph, "src/api"),
..report
};
assert_eq!(expected, actual);
}
#[test]
fn should_return_no_symbols_under_path_note_when_prefix_matches_nothing() {
let report = apply_entry_pivot(report_with_api_and_util(), "no/such/path");
let actual = entry_pivot_empty_note(&report, "no/such/path");
assert_eq!(
Some("note: no symbols under no/such/path".to_string()),
actual
);
}
#[test]
fn should_return_none_when_prefix_matches_at_least_one_symbol() {
let report = apply_entry_pivot(report_with_api_and_util(), "src/api");
let actual = entry_pivot_empty_note(&report, "src/api");
assert_eq!(None, actual);
}
#[test]
fn should_return_none_when_report_graph_has_no_nodes_at_all() {
let report = Report {
origin: rinkaku_core::render::ReportOrigin::Diff,
files: vec![],
skipped: vec![],
graph: rinkaku_core::graph::SymbolGraph {
nodes: vec![],
edges: vec![],
roots: vec![],
},
tests: vec![],
fan_ins: vec![],
file_size_warnings: vec![],
file_size_bands: vec![],
removed: vec![],
};
let actual = entry_pivot_empty_note(&report, "src/api");
assert_eq!(None, actual);
}
}
mod repo_outline_empty_note_tests {
use super::*;
use pretty_assertions::assert_eq;
use rinkaku_core::render::Report;
fn empty_graph() -> rinkaku_core::graph::SymbolGraph {
rinkaku_core::graph::SymbolGraph {
nodes: vec![],
edges: vec![],
roots: vec![],
}
}
fn empty_report() -> Report {
Report {
origin: rinkaku_core::render::ReportOrigin::RepoOutline,
files: vec![],
skipped: vec![],
graph: empty_graph(),
tests: vec![],
fan_ins: vec![],
file_size_warnings: vec![],
file_size_bands: vec![],
removed: vec![],
}
}
#[test]
fn should_return_note_when_report_has_no_files_and_no_removed() {
let actual = repo_outline_empty_note(&empty_report());
assert_eq!(
Some("note: no supported source files found in the repository"),
actual
);
}
#[test]
fn should_return_none_when_report_has_file_entries() {
let report = Report {
files: vec![rinkaku_core::render::FileReport {
path: "src/lib.rs".to_string(),
symbols: vec![],
}],
..empty_report()
};
let actual = repo_outline_empty_note(&report);
assert_eq!(None, actual);
}
#[test]
fn should_return_none_when_report_has_removed_entries() {
let report = Report {
removed: vec![rinkaku_core::extract::RemovedSymbol {
name: "old_helper".to_string(),
kind: rinkaku_core::extract::SymbolKind::Function,
path: "src/lib.rs".to_string(),
signature: "fn old_helper()".to_string(),
}],
..empty_report()
};
let actual = repo_outline_empty_note(&report);
assert_eq!(None, actual);
}
}
}