1use std::sync::Arc;
4
5use eure::query::{ParseCst, ParseDocument, TextFile};
6use eure::report::{ErrorReports, Origin, format_error_reports};
7use eure_document::document::EureDocument;
8use eure_document::parse::ParseError;
9use eure_tree::prelude::Cst;
10use eure_tree::tree::InputSpan;
11use query_flow::{Db, QueryError, query};
12
13use crate::document::EumdDocument;
14use crate::report::EumdReportContext;
15use crate::{check_references_with_spans, report_check_errors};
16
17#[derive(Clone, PartialEq)]
19pub struct ParsedEumd {
20 pub doc: Arc<EumdDocument>,
22 pub eure_doc: Arc<EureDocument>,
24 pub cst: Arc<Cst>,
26 pub origins: Arc<eure::document::OriginMap>,
28}
29
30#[query]
38pub fn parse_eumd_document(db: &impl Db, file: TextFile) -> Result<ParsedEumd, QueryError> {
39 let parsed_doc = db.query(ParseDocument::new(file.clone()))?;
41
42 let parsed_cst = db.query(ParseCst::new(file.clone()))?;
44
45 let root_id = parsed_doc.doc.get_root_id();
47 let eumd_doc: EumdDocument = parsed_doc.doc.parse(root_id).map_err(|e: ParseError| {
48 let span = parsed_doc
52 .origins
53 .get_value_span(e.node_id, &parsed_cst.cst)
54 .unwrap_or(InputSpan::EMPTY);
55 let origin = Origin::new(file.clone(), span);
56 ErrorReports::from(vec![eure::report::ErrorReport::error(
57 e.to_string(),
58 origin,
59 )])
60 })?;
61
62 Ok(ParsedEumd {
63 doc: Arc::new(eumd_doc),
64 eure_doc: parsed_doc.doc.clone(),
65 cst: Arc::new(parsed_cst.cst.clone()),
66 origins: parsed_doc.origins.clone(),
67 })
68}
69
70#[query]
78pub fn check_eumd_references(db: &impl Db, file: TextFile) -> Result<ErrorReports, QueryError> {
79 let parsed = db.query(ParseEumdDocument::new(file.clone()))?;
80
81 let result = check_references_with_spans(&parsed.doc, &parsed.eure_doc);
83
84 if result.is_ok() {
85 Ok(ErrorReports::new())
86 } else {
87 let ctx = EumdReportContext {
89 file,
90 cst: &parsed.cst,
91 origins: &parsed.origins,
92 };
93 Ok(report_check_errors(&result, &ctx))
94 }
95}
96
97#[query]
105pub fn check_eumd_references_formatted(
106 db: &impl Db,
107 file: TextFile,
108) -> Result<Vec<String>, QueryError> {
109 let reports = db.query(CheckEumdReferences::new(file))?;
110
111 let mut formatted = Vec::new();
113 for r in reports.iter() {
114 let single = ErrorReports::from(vec![r.clone()]);
115 let s = format_error_reports(db, &single, false)?;
116 formatted.push(s.trim().to_string());
117 }
118 Ok(formatted)
119}