morphir_core/migration/
diagnostic.rs1use serde::{Deserialize, Serialize};
2
3use crate::traversal::IrCursor;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
6#[serde(rename_all = "lowercase")]
7pub enum Severity {
8 Warning,
9 Error,
10}
11
12#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
13pub enum V4Encoding {
14 #[default]
15 Compact,
16 Expanded,
17}
18
19#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
20pub struct MigrationOptions {
21 pub allow_partial: bool,
22 pub encoding: V4Encoding,
23}
24
25#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
26#[serde(rename_all = "camelCase")]
27pub struct MigrationDiagnostic {
28 pub severity: Severity,
29 pub code: &'static str,
30 pub path: String,
31 pub message: String,
32 #[serde(skip_serializing_if = "Option::is_none")]
33 pub help: Option<String>,
34 #[serde(skip)]
35 pub recoverable: bool,
36 #[serde(skip)]
37 cursor: IrCursor,
38}
39
40impl MigrationDiagnostic {
41 pub fn error(code: &'static str, cursor: IrCursor, message: impl Into<String>) -> Self {
42 let path = cursor.to_string();
43 Self {
44 severity: Severity::Error,
45 code,
46 path,
47 message: message.into(),
48 help: None,
49 recoverable: false,
50 cursor,
51 }
52 }
53
54 pub fn recoverable(code: &'static str, cursor: IrCursor, message: impl Into<String>) -> Self {
55 let path = cursor.to_string();
56 Self {
57 severity: Severity::Error,
58 code,
59 path,
60 message: message.into(),
61 help: None,
62 recoverable: true,
63 cursor,
64 }
65 }
66
67 pub fn warning(code: &'static str, cursor: IrCursor, message: impl Into<String>) -> Self {
68 let path = cursor.to_string();
69 Self {
70 severity: Severity::Warning,
71 code,
72 path,
73 message: message.into(),
74 help: None,
75 recoverable: true,
76 cursor,
77 }
78 }
79
80 pub fn with_help(mut self, help: impl Into<String>) -> Self {
81 self.help = Some(help.into());
82 self
83 }
84
85 pub fn cursor(&self) -> &IrCursor {
87 &self.cursor
88 }
89}
90
91#[derive(Debug, Clone)]
92pub struct MigrationReport {
93 options: MigrationOptions,
94 diagnostics: Vec<MigrationDiagnostic>,
95}
96
97impl MigrationReport {
98 pub fn new(options: MigrationOptions) -> Self {
99 Self {
100 options,
101 diagnostics: Vec::new(),
102 }
103 }
104
105 pub fn push(&mut self, diagnostic: MigrationDiagnostic) {
106 self.diagnostics.push(diagnostic);
107 }
108
109 pub fn diagnostics(&self) -> &[MigrationDiagnostic] {
110 &self.diagnostics
111 }
112
113 pub fn can_publish(&self) -> bool {
114 self.diagnostics.iter().all(|diagnostic| {
115 diagnostic.severity != Severity::Error
116 || (self.options.allow_partial && diagnostic.recoverable)
117 })
118 }
119}