Skip to main content

reifydb_value/error/
macro.rs

1// SPDX-License-Identifier: MIT
2// Copyright (c) 2026 ReifyDB
3
4#[macro_export]
5macro_rules! error {
6	($diagnostic:expr) => {
7		$crate::error::Error(Box::new($diagnostic))
8	};
9	($diagnostic:expr, $fragment:expr) => {{
10		let mut diag = $diagnostic;
11		diag.with_fragment($fragment.into());
12		$crate::error::Error(Box::new(diag))
13	}};
14}
15
16#[macro_export]
17macro_rules! return_error {
18	($diagnostic:expr) => {
19		return Err($crate::error::Error(Box::new($diagnostic)))
20	};
21	($diagnostic:expr, $fragment:expr) => {{
22		let mut diag = $diagnostic;
23		diag.with_fragment($fragment.into());
24		return Err($crate::error::Error(Box::new(diag)));
25	}};
26}
27
28#[macro_export]
29macro_rules! err {
30	($diagnostic:expr) => {
31		Err($crate::error::Error(Box::new($diagnostic)))
32	};
33	($diagnostic:expr, $fragment:expr) => {{
34		let mut diag = $diagnostic;
35		diag.with_fragment($fragment.into());
36		Err($crate::error::Error(Box::new(diag)))
37	}};
38}
39
40#[cfg(test)]
41pub mod tests {
42	use std::sync::Arc;
43
44	use crate::{
45		error::{Error, IntoDiagnostic, TypeError},
46		fragment::{Fragment, StatementColumn, StatementLine},
47	};
48
49	#[test]
50	fn test_error_macro() {
51		// Test that error! macro creates correct Error type
52		let err = error!(TypeError::NanNotAllowed.into_diagnostic());
53
54		// Verify it creates the correct Error type
55		assert!(matches!(err, Error(_)));
56
57		// Test that the diagnostic is properly wrapped
58		let diagnostic = err.diagnostic();
59		assert!(diagnostic.message.contains("NaN"));
60	}
61
62	#[test]
63	fn test_return_error_macro() {
64		fn test_fn() -> Result<(), Error> {
65			return_error!(TypeError::NanNotAllowed.into_diagnostic());
66		}
67
68		let result = test_fn();
69		assert!(result.is_err());
70
71		if let Err(err) = result {
72			let diagnostic = err.diagnostic();
73			assert!(diagnostic.message.contains("NaN"));
74		}
75	}
76
77	#[test]
78	fn test_err_macro() {
79		// Test that err! macro creates correct Result type with Err
80		let result: Result<(), Error> = err!(TypeError::NanNotAllowed.into_diagnostic());
81
82		assert!(result.is_err());
83
84		if let Err(err) = result {
85			let diagnostic = err.diagnostic();
86			assert!(diagnostic.message.contains("NaN"));
87		}
88	}
89
90	#[test]
91	fn test_error_macro_with_fragment() {
92		// Create a test fragment
93		let fragment = Fragment::Statement {
94			line: StatementLine(42),
95			column: StatementColumn(10),
96			text: Arc::from("test fragment"),
97		};
98
99		// Test that error! macro with fragment creates correct Error
100		// type
101		let err = error!(TypeError::NanNotAllowed.into_diagnostic(), fragment.clone());
102
103		// Verify it creates the correct Error type
104		assert!(matches!(err, Error(_)));
105
106		// Test that the diagnostic has the origin set (via fragment)
107		let diagnostic = err.diagnostic();
108		let fragment = diagnostic.fragment();
109		assert!(fragment.is_some());
110		if let Some(Fragment::Statement {
111			line,
112			column,
113			..
114		}) = fragment.as_ref()
115		{
116			assert_eq!(line.0, 42);
117			assert_eq!(column.0, 10);
118		}
119	}
120
121	#[test]
122	fn test_return_error_macro_with_fragment() {
123		fn test_fn() -> Result<(), Error> {
124			let fragment = Fragment::Statement {
125				line: StatementLine(100),
126				column: StatementColumn(25),
127				text: Arc::from("error location"),
128			};
129			return_error!(TypeError::NanNotAllowed.into_diagnostic(), fragment);
130		}
131
132		let result = test_fn();
133		assert!(result.is_err());
134
135		if let Err(err) = result {
136			let diagnostic = err.diagnostic();
137			let fragment = diagnostic.fragment();
138			assert!(fragment.is_some());
139			if let Some(Fragment::Statement {
140				line,
141				column,
142				..
143			}) = fragment.as_ref()
144			{
145				assert_eq!(line.0, 100);
146				assert_eq!(column.0, 25);
147			}
148		}
149	}
150
151	#[test]
152	fn test_err_macro_with_fragment() {
153		let fragment = Fragment::Statement {
154			line: StatementLine(200),
155			column: StatementColumn(50),
156			text: Arc::from("err fragment test"),
157		};
158
159		// Test that err! macro with fragment creates correct Result
160		// type with Err
161		let result: Result<(), Error> = err!(TypeError::NanNotAllowed.into_diagnostic(), fragment);
162
163		assert!(result.is_err());
164
165		if let Err(err) = result {
166			let diagnostic = err.diagnostic();
167			let fragment = diagnostic.fragment();
168			assert!(fragment.is_some());
169			if let Some(Fragment::Statement {
170				line,
171				column,
172				..
173			}) = fragment.as_ref()
174			{
175				assert_eq!(line.0, 200);
176				assert_eq!(column.0, 50);
177			}
178		}
179	}
180
181	#[test]
182	fn test_macros_with_closure_fragment() {
183		// Test with closure that returns Fragment (implements
184		// Into<Fragment>)
185		let get_fragment = || Fragment::Statement {
186			line: StatementLine(300),
187			column: StatementColumn(75),
188			text: Arc::from("closure fragment"),
189		};
190
191		let err = error!(TypeError::NanNotAllowed.into_diagnostic(), get_fragment());
192		let diagnostic = err.diagnostic();
193		let fragment = diagnostic.fragment();
194		assert!(fragment.is_some());
195		assert_eq!(fragment.as_ref().unwrap().line().0, 300);
196	}
197}