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
50 .origins
51 .get_value_span(e.node_id, &parsed_cst.cst)
52 .unwrap_or(InputSpan::EMPTY);
53 let origin = Origin::new(file.clone(), span);
54 ErrorReports::from(vec![eure::report::ErrorReport::error(
55 e.to_string(),
56 origin,
57 )])
58 })?;
59
60 Ok(ParsedEumd {
61 doc: Arc::new(eumd_doc),
62 eure_doc: parsed_doc.doc.clone(),
63 cst: Arc::new(parsed_cst.cst.clone()),
64 origins: parsed_doc.origins.clone(),
65 })
66}
67
68#[query]
76pub fn check_eumd_references(db: &impl Db, file: TextFile) -> Result<ErrorReports, QueryError> {
77 let parsed = db.query(ParseEumdDocument::new(file.clone()))?;
78
79 let result = check_references_with_spans(&parsed.doc, &parsed.eure_doc);
81
82 if result.is_ok() {
83 Ok(ErrorReports::new())
84 } else {
85 let ctx = EumdReportContext {
87 file,
88 cst: &parsed.cst,
89 origins: &parsed.origins,
90 };
91 Ok(report_check_errors(&result, &ctx))
92 }
93}
94
95#[query]
103pub fn check_eumd_references_formatted(
104 db: &impl Db,
105 file: TextFile,
106) -> Result<Vec<String>, QueryError> {
107 let reports = db.query(CheckEumdReferences::new(file))?;
108
109 let mut formatted = Vec::new();
111 for r in reports.iter() {
112 let single = ErrorReports::from(vec![r.clone()]);
113 let s = format_error_reports(db, &single, false)?;
114 formatted.push(s.trim().to_string());
115 }
116 Ok(formatted)
117}