NAC_Blockchain/protocol/nac-constitution-macros/src/error.rs

244 lines
6.8 KiB
Rust

//! 宪法宏错误处理模块 - 完整实现
use std::fmt;
/// 宏错误类型
#[derive(Debug, Clone)]
pub enum MacroError {
/// 缺少必需参数
MissingParameter {
parameter: String,
span_info: String,
},
/// 无效的参数值
InvalidParameter {
parameter: String,
value: String,
expected: String,
},
/// 类型检查失败
TypeCheckFailed {
expected_type: String,
actual_type: String,
location: String,
},
/// 边界检查失败
BoundaryCheckFailed {
value: String,
min: Option<String>,
max: Option<String>,
},
/// 表达式解析失败
ExpressionParseFailed {
expression: String,
error: String,
},
/// 代码生成失败
CodeGenerationFailed {
reason: String,
},
/// 元数据生成失败
MetadataGenerationFailed {
reason: String,
},
/// 未知错误
Unknown {
message: String,
},
}
impl MacroError {
/// 转换为编译错误
pub fn to_compile_error(&self) -> proc_macro2::TokenStream {
let message = self.to_string();
quote::quote! {
compile_error!(#message);
}
}
/// 创建缺少参数错误
pub fn missing_parameter(parameter: impl Into<String>, span_info: impl Into<String>) -> Self {
Self::MissingParameter {
parameter: parameter.into(),
span_info: span_info.into(),
}
}
/// 创建无效参数错误
pub fn invalid_parameter(
parameter: impl Into<String>,
value: impl Into<String>,
expected: impl Into<String>,
) -> Self {
Self::InvalidParameter {
parameter: parameter.into(),
value: value.into(),
expected: expected.into(),
}
}
/// 创建类型检查失败错误
pub fn type_check_failed(
expected_type: impl Into<String>,
actual_type: impl Into<String>,
location: impl Into<String>,
) -> Self {
Self::TypeCheckFailed {
expected_type: expected_type.into(),
actual_type: actual_type.into(),
location: location.into(),
}
}
/// 创建边界检查失败错误
pub fn boundary_check_failed(
value: impl Into<String>,
min: Option<String>,
max: Option<String>,
) -> Self {
Self::BoundaryCheckFailed {
value: value.into(),
min,
max,
}
}
/// 创建表达式解析失败错误
pub fn expression_parse_failed(
expression: impl Into<String>,
error: impl Into<String>,
) -> Self {
Self::ExpressionParseFailed {
expression: expression.into(),
error: error.into(),
}
}
/// 创建代码生成失败错误
pub fn code_generation_failed(reason: impl Into<String>) -> Self {
Self::CodeGenerationFailed {
reason: reason.into(),
}
}
/// 创建元数据生成失败错误
pub fn metadata_generation_failed(reason: impl Into<String>) -> Self {
Self::MetadataGenerationFailed {
reason: reason.into(),
}
}
/// 创建未知错误
pub fn unknown(message: impl Into<String>) -> Self {
Self::Unknown {
message: message.into(),
}
}
}
impl fmt::Display for MacroError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::MissingParameter { parameter, span_info } => {
write!(
f,
"Missing required parameter '{}' at {}",
parameter, span_info
)
}
Self::InvalidParameter {
parameter,
value,
expected,
} => {
write!(
f,
"Invalid value '{}' for parameter '{}', expected: {}",
value, parameter, expected
)
}
Self::TypeCheckFailed {
expected_type,
actual_type,
location,
} => {
write!(
f,
"Type check failed at {}: expected '{}', found '{}'",
location, expected_type, actual_type
)
}
Self::BoundaryCheckFailed { value, min, max } => {
let bounds = match (min, max) {
(Some(min), Some(max)) => format!("between {} and {}", min, max),
(Some(min), None) => format!(">= {}", min),
(None, Some(max)) => format!("<= {}", max),
(None, None) => "within valid range".to_string(),
};
write!(f, "Boundary check failed: value '{}' must be {}", value, bounds)
}
Self::ExpressionParseFailed { expression, error } => {
write!(
f,
"Failed to parse expression '{}': {}",
expression, error
)
}
Self::CodeGenerationFailed { reason } => {
write!(f, "Code generation failed: {}", reason)
}
Self::MetadataGenerationFailed { reason } => {
write!(f, "Metadata generation failed: {}", reason)
}
Self::Unknown { message } => {
write!(f, "Unknown error: {}", message)
}
}
}
}
impl std::error::Error for MacroError {}
impl From<syn::Error> for MacroError {
fn from(error: syn::Error) -> Self {
Self::Unknown {
message: error.to_string(),
}
}
}
impl From<MacroError> for syn::Error {
fn from(error: MacroError) -> Self {
syn::Error::new(proc_macro2::Span::call_site(), error.to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_missing_parameter_error() {
let error = MacroError::missing_parameter("clause", "line 10");
assert!(error.to_string().contains("Missing required parameter 'clause'"));
}
#[test]
fn test_invalid_parameter_error() {
let error = MacroError::invalid_parameter("check", "invalid", "boolean expression");
assert!(error.to_string().contains("Invalid value 'invalid'"));
}
#[test]
fn test_type_check_failed_error() {
let error = MacroError::type_check_failed("u64", "String", "parameter 'amount'");
assert!(error.to_string().contains("Type check failed"));
}
#[test]
fn test_boundary_check_failed_error() {
let error = MacroError::boundary_check_failed("150", Some("0".to_string()), Some("100".to_string()));
assert!(error.to_string().contains("Boundary check failed"));
}
}