1use std::path::{Path, PathBuf};
2
3use pfx_editor_doc::toml_edit::DocumentMut;
4use pfx_editor_toml::{Check, Diagnostic, Location, Severity};
5use pfx_scene::Project;
6
7pub struct SceneCheck<'a> {
8 project: &'a Project,
9}
10
11fn severity(found: pfx_scene::Severity) -> Severity {
12 match found {
13 pfx_scene::Severity::Error => Severity::Error,
14 pfx_scene::Severity::Warning => Severity::Warning,
15 }
16}
17
18impl<'a> SceneCheck<'a> {
19 pub fn new(project: &'a Project) -> SceneCheck<'a> {
20 SceneCheck { project }
21 }
22
23 fn place(&self, file: &Path) -> PathBuf {
24 if file.is_absolute() {
25 file.to_path_buf()
26 } else {
27 self.project.root().join(file)
28 }
29 }
30
31 pub fn convert(&self, found: pfx_scene::Diagnostic, file: Option<&Path>) -> Diagnostic {
32 Diagnostic {
33 file: file.map_or_else(|| self.place(&found.file), Path::to_path_buf),
34 line: found.line,
35 column: found.column,
36 end_line: found.end_line,
37 end_column: found.end_column,
38 severity: severity(found.severity),
39 code: found.code.to_string(),
40 key: found.key,
41 message: found.message,
42 related: found
43 .related
44 .into_iter()
45 .map(|related| Location {
46 file: self.place(&related.file),
47 line: related.line,
48 column: related.column,
49 })
50 .collect(),
51 }
52 }
53
54 pub fn all(&self) -> Vec<Diagnostic> {
55 self.project
56 .check()
57 .into_iter()
58 .map(|found| self.convert(found, None))
59 .collect()
60 }
61}
62
63impl Check for SceneCheck<'_> {
64 fn check(&self, file: &Path, text: &str, _doc: &DocumentMut) -> Vec<Diagnostic> {
65 pfx_scene::check(text, file, self.project)
66 .into_iter()
67 .map(|found| self.convert(found, Some(file)))
68 .collect()
69 }
70}
71
72pub fn worded(problem: &Diagnostic, root: &Path) -> String {
73 let file = crate::outline::relative(root, &problem.file);
74 let kind = match problem.severity {
75 Severity::Error => "error",
76 Severity::Warning => "warning",
77 };
78 format!(
79 "{file}:{}:{}: {kind}: {}",
80 problem.line, problem.column, problem.message
81 )
82}