244 lines
6.8 KiB
Rust
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"));
|
|
}
|
|
}
|