Show source names in diagnostics
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use decodal_core::{
|
||||
Data, Diagnostic, DiagnosticKind, EmptyLoader, Engine, LoadedSource, SourceLoader, Span,
|
||||
Data, Diagnostic, DiagnosticKind, EmptyLoader, Engine, LoadedSource, SourceId, SourceLoader,
|
||||
Span, format_diagnostic_with,
|
||||
};
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
@@ -24,11 +25,18 @@ fn encode_result(result: Result<String, String>) -> String {
|
||||
|
||||
fn evaluate_inner(source: &str) -> Result<String, String> {
|
||||
let mut engine = Engine::new(EmptyLoader);
|
||||
let module = engine
|
||||
.add_root_source("playground", "playground", source)
|
||||
.map_err(format_diagnostic)?;
|
||||
let value = engine.eval_module(module).map_err(format_diagnostic)?;
|
||||
let data = engine.materialize(&value).map_err(format_diagnostic)?;
|
||||
let module = match engine.add_root_source("playground", "playground", source) {
|
||||
Ok(module) => module,
|
||||
Err(error) => return Err(format_diagnostic_with_root(&error, "playground")),
|
||||
};
|
||||
let value = match engine.eval_module(module) {
|
||||
Ok(value) => value,
|
||||
Err(error) => return Err(engine.format_diagnostic(&error)),
|
||||
};
|
||||
let data = match engine.materialize(&value) {
|
||||
Ok(data) => data,
|
||||
Err(error) => return Err(engine.format_diagnostic(&error)),
|
||||
};
|
||||
Ok(format_data(&data, 0))
|
||||
}
|
||||
|
||||
@@ -48,11 +56,18 @@ fn evaluate_project_inner(entry: &str, files_json: &str) -> Result<String, Strin
|
||||
.ok_or_else(|| format!("entry file `{entry}` was not found"))?;
|
||||
|
||||
let mut engine = Engine::new(VirtualLoader { files });
|
||||
let module = engine
|
||||
.add_root_source(entry.clone(), entry.clone(), &source)
|
||||
.map_err(format_diagnostic)?;
|
||||
let value = engine.eval_module(module).map_err(format_diagnostic)?;
|
||||
let data = engine.materialize(&value).map_err(format_diagnostic)?;
|
||||
let module = match engine.add_root_source(entry.clone(), entry.clone(), &source) {
|
||||
Ok(module) => module,
|
||||
Err(error) => return Err(format_diagnostic_with_root(&error, &entry)),
|
||||
};
|
||||
let value = match engine.eval_module(module) {
|
||||
Ok(value) => value,
|
||||
Err(error) => return Err(engine.format_diagnostic(&error)),
|
||||
};
|
||||
let data = match engine.materialize(&value) {
|
||||
Ok(data) => data,
|
||||
Err(error) => return Err(engine.format_diagnostic(&error)),
|
||||
};
|
||||
Ok(format_data(&data, 0))
|
||||
}
|
||||
|
||||
@@ -124,22 +139,10 @@ fn normalize_path(path: &str) -> Option<String> {
|
||||
}
|
||||
}
|
||||
|
||||
fn format_diagnostic(diagnostic: decodal_core::Diagnostic) -> String {
|
||||
let mut out = format!(
|
||||
"{:?} at {}:{}..{}: {}",
|
||||
diagnostic.kind,
|
||||
diagnostic.span.source.0,
|
||||
diagnostic.span.start,
|
||||
diagnostic.span.end,
|
||||
diagnostic.message,
|
||||
);
|
||||
for label in diagnostic.labels {
|
||||
out.push_str(&format!(
|
||||
"\nnote at {}:{}..{}: {}",
|
||||
label.span.source.0, label.span.start, label.span.end, label.message,
|
||||
));
|
||||
}
|
||||
out
|
||||
fn format_diagnostic_with_root(diagnostic: &decodal_core::Diagnostic, root_name: &str) -> String {
|
||||
format_diagnostic_with(diagnostic, |source| {
|
||||
(source == SourceId(0)).then_some(root_name)
|
||||
})
|
||||
}
|
||||
|
||||
fn format_data(data: &Data, indent: usize) -> String {
|
||||
@@ -237,4 +240,17 @@ mod tests {
|
||||
let output = evaluate_project_inner("main.dcdl", files).unwrap();
|
||||
assert!(output.contains("\"port\": 9443"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn project_diagnostics_use_virtual_file_names() {
|
||||
let files = r#"{
|
||||
"main.dcdl":"let dep = import \"./schemas/service.dcdl\"; in dep.Service & { port = 80; }",
|
||||
"schemas/service.dcdl":"Service = { port = Int & > 443 default 8443; }"
|
||||
}"#;
|
||||
let error = evaluate_project_inner("main.dcdl", files).unwrap_err();
|
||||
assert!(error.contains("main.dcdl:"));
|
||||
assert!(error.contains("schemas/service.dcdl:"));
|
||||
assert!(!error.contains("source 0:"));
|
||||
assert!(!error.contains("source 1:"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user