use crate::{
cancellation::{CancellationFlag, Outcome},
error::Error,
parser, validator,
wiki::Wiki,
};
use std::path::Path;
pub fn analyze(
source_path: Option<&Path>,
source_contents: &str,
cancellation: &CancellationFlag,
) -> Outcome<Result<Wiki, Vec<Error>>> {
let (wiki, mut errors) = parser::parse_with_recovery(source_path, source_contents);
validator::validate(&wiki, source_path, source_contents, cancellation).map(|result| {
if let Err(validation_errors) = result {
errors.extend(validation_errors);
}
if errors.is_empty() {
Ok(wiki)
} else {
Err(errors)
}
})
}
#[cfg(test)]
mod tests {
use super::analyze;
use crate::{cancellation::CancellationFlag, error::Error, wiki::Wiki};
fn analyze_test(source_contents: &str) -> Result<Wiki, Vec<Error>> {
analyze(None, source_contents, &CancellationFlag::default()).assume_completed()
}
#[test]
fn validation_errors_accompany_syntax_errors() {
let errors =
analyze_test("# Home\nSee [Missing] and [Greeting].\n# Greeting\nUnexpected].")
.unwrap_err();
assert_eq!(errors.len(), 2);
assert!(
errors[0]
.to_string()
.contains("Unexpected closing link delimiter."),
);
assert!(errors[1].to_string().contains("Node `Missing` not found."));
}
#[test]
fn syntax_errors_preserve_reachability() {
let errors =
analyze_test("# Home\nSee [Greeting].\n# Greeting\nStray] and [Farewell].\n# Farewell")
.unwrap_err();
assert_eq!(errors.len(), 1);
assert!(
errors[0]
.to_string()
.contains("Unexpected closing link delimiter."),
);
}
#[test]
fn malformed_links_are_not_validated() {
let errors = analyze_test("# Home\nSee [Missing[Home].").unwrap_err();
assert_eq!(errors.len(), 1);
assert!(
errors[0]
.to_string()
.contains("Unexpected opening link delimiter."),
);
}
#[test]
fn valid_wiki() {
assert!(analyze_test("# Home\nSee [Greeting].\n# Greeting").is_ok());
}
}