1use serde::{Deserialize, Serialize};
2
3use crate::abi::{swc_ast, SpanIR};
4#[cfg(feature = "swc")]
5use swc_core::common::{SyntaxContext, DUMMY_SP};
6
7#[derive(Serialize, Deserialize)]
9#[derive(Clone, Debug, PartialEq)]
10pub enum Patch {
11 Insert {
12 at: SpanIR,
13 code: PatchCode,
14 #[serde(default)]
16 source_macro: Option<String>,
17 },
18 Replace {
19 span: SpanIR,
20 code: PatchCode,
21 #[serde(default)]
23 source_macro: Option<String>,
24 },
25 Delete {
26 span: SpanIR,
27 },
28 InsertRaw {
29 at: SpanIR,
30 code: String,
31 context: Option<String>,
32 #[serde(default)]
34 source_macro: Option<String>,
35 },
36 ReplaceRaw {
37 span: SpanIR,
38 code: String,
39 context: Option<String>,
40 #[serde(default)]
42 source_macro: Option<String>,
43 },
44}
45
46impl Patch {
47 pub fn source_macro(&self) -> Option<&str> {
49 match self {
50 Patch::Insert { source_macro, .. } => source_macro.as_deref(),
51 Patch::Replace { source_macro, .. } => source_macro.as_deref(),
52 Patch::Delete { .. } => None,
53 Patch::InsertRaw { source_macro, .. } => source_macro.as_deref(),
54 Patch::ReplaceRaw { source_macro, .. } => source_macro.as_deref(),
55 }
56 }
57
58 pub fn with_source_macro(self, macro_name: &str) -> Self {
60 match self {
61 Patch::Insert { at, code, .. } => Patch::Insert {
62 at,
63 code,
64 source_macro: Some(macro_name.to_string()),
65 },
66 Patch::Replace { span, code, .. } => Patch::Replace {
67 span,
68 code,
69 source_macro: Some(macro_name.to_string()),
70 },
71 Patch::Delete { span } => Patch::Delete { span },
72 Patch::InsertRaw { at, code, context, .. } => Patch::InsertRaw {
73 at,
74 code,
75 context,
76 source_macro: Some(macro_name.to_string()),
77 },
78 Patch::ReplaceRaw { span, code, context, .. } => Patch::ReplaceRaw {
79 span,
80 code,
81 context,
82 source_macro: Some(macro_name.to_string()),
83 },
84 }
85 }
86}
87
88#[derive(Clone, Debug, PartialEq)]
89pub enum PatchCode {
90 Text(String),
91 ClassMember(swc_ast::ClassMember),
92 Stmt(swc_ast::Stmt),
93 ModuleItem(swc_ast::ModuleItem),
94}
95
96impl serde::Serialize for PatchCode {
98 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
99 where
100 S: serde::Serializer,
101 {
102 match self {
103 PatchCode::Text(s) => serializer.serialize_str(s),
104 _ => serializer.serialize_str("/* AST node - cannot serialize */"),
105 }
106 }
107}
108
109impl<'de> serde::Deserialize<'de> for PatchCode {
110 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
111 where
112 D: serde::Deserializer<'de>,
113 {
114 let s = String::deserialize(deserializer)?;
115 Ok(PatchCode::Text(s))
116 }
117}
118
119impl From<String> for PatchCode {
120 fn from(value: String) -> Self {
121 PatchCode::Text(value)
122 }
123}
124
125impl From<&str> for PatchCode {
126 fn from(value: &str) -> Self {
127 PatchCode::Text(value.to_string())
128 }
129}
130
131impl From<swc_ast::ClassMember> for PatchCode {
132 fn from(member: swc_ast::ClassMember) -> Self {
133 PatchCode::ClassMember(member)
134 }
135}
136
137impl From<swc_ast::Stmt> for PatchCode {
138 fn from(stmt: swc_ast::Stmt) -> Self {
139 PatchCode::Stmt(stmt)
140 }
141}
142
143impl From<swc_ast::ModuleItem> for PatchCode {
144 fn from(item: swc_ast::ModuleItem) -> Self {
145 PatchCode::ModuleItem(item)
146 }
147}
148
149impl From<Vec<swc_ast::Stmt>> for PatchCode {
150 fn from(stmts: Vec<swc_ast::Stmt>) -> Self {
151 if stmts.len() == 1 {
153 PatchCode::Stmt(stmts.into_iter().next().unwrap())
154 } else {
155 PatchCode::Stmt(swc_ast::Stmt::Block(swc_ast::BlockStmt {
156 span: DUMMY_SP,
157 ctxt: SyntaxContext::empty(),
158 stmts,
159 }))
160 }
161 }
162}
163
164impl From<Vec<swc_ast::ModuleItem>> for PatchCode {
165 fn from(items: Vec<swc_ast::ModuleItem>) -> Self {
166 if items.len() == 1 {
168 PatchCode::ModuleItem(items.into_iter().next().unwrap())
169 } else {
170 let code = items
173 .iter()
174 .map(|_| "/* generated code */")
175 .collect::<Vec<_>>()
176 .join("\n");
177 PatchCode::Text(code)
178 }
179 }
180}
181
182#[derive(Serialize, Deserialize)]
183#[derive(Clone, Debug, Default)]
184pub struct MacroResult {
185 pub runtime_patches: Vec<Patch>,
187 pub type_patches: Vec<Patch>,
189 pub diagnostics: Vec<Diagnostic>,
191 pub tokens: Option<String>,
193 pub debug: Option<String>,
195}
196
197#[derive(Serialize, Deserialize)]
198#[derive(Clone, Debug, PartialEq)]
199pub struct Diagnostic {
200 pub level: DiagnosticLevel,
201 pub message: String,
202 pub span: Option<SpanIR>,
203 pub notes: Vec<String>,
205 pub help: Option<String>,
207}
208
209#[derive(Serialize, Deserialize)]
210#[derive(Clone, Debug, PartialEq, Eq)]
211pub enum DiagnosticLevel {
212 Error,
213 Warning,
214 Info,
215}