454 lines
16 KiB
Rust
454 lines
16 KiB
Rust
//! 宪法宏代码生成模块 - 完整实现
|
||
//!
|
||
//! 提供完整的代码生成、测试生成和文档生成功能。
|
||
|
||
use crate::error::MacroError;
|
||
use crate::metadata::{FunctionMetadata, ClauseMetadata};
|
||
use quote::quote;
|
||
use syn::{Ident, ItemFn, Type};
|
||
|
||
/// 代码生成器
|
||
pub struct CodeGenerator;
|
||
|
||
impl CodeGenerator {
|
||
/// 生成宪法检查代码
|
||
pub fn generate_constitutional_check(
|
||
clause_id: &str,
|
||
strict: bool,
|
||
) -> proc_macro2::TokenStream {
|
||
if strict {
|
||
quote! {
|
||
// 严格模式:条款不存在或未激活时panic
|
||
let clause = nac_constitution_state::get_clause(#clause_id)
|
||
.expect(&format!("Constitutional clause '{}' not found", #clause_id));
|
||
|
||
if !clause.is_active() {
|
||
panic!("Constitutional clause '{}' is not active", #clause_id);
|
||
}
|
||
|
||
log::debug!("Constitutional check passed: clause={}, version={}", #clause_id, clause.version);
|
||
}
|
||
} else {
|
||
quote! {
|
||
// 非严格模式:返回错误
|
||
if let Some(clause) = nac_constitution_state::get_clause(#clause_id) {
|
||
if !clause.is_active() {
|
||
log::error!("Constitutional clause '{}' is not active", #clause_id);
|
||
return Err(ConstitutionalError::ClauseNotActive(#clause_id.to_string()).into());
|
||
}
|
||
log::debug!("Constitutional check passed: clause={}, version={}", #clause_id, clause.version);
|
||
} else {
|
||
log::error!("Constitutional clause '{}' not found", #clause_id);
|
||
return Err(ConstitutionalError::ClauseNotFound(#clause_id.to_string()).into());
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 生成前置条件检查代码
|
||
pub fn generate_precondition_check(
|
||
check_expr: &str,
|
||
error_message: &str,
|
||
strict: bool,
|
||
) -> Result<proc_macro2::TokenStream, MacroError> {
|
||
let check_tokens: proc_macro2::TokenStream = check_expr.parse()
|
||
.map_err(|e| MacroError::expression_parse_failed(check_expr, format!("{}", e)))?;
|
||
|
||
if strict {
|
||
Ok(quote! {
|
||
// 严格模式:检查失败时panic
|
||
if !(#check_tokens) {
|
||
panic!("Precondition check failed: {} - {}", #check_expr, #error_message);
|
||
}
|
||
log::debug!("Precondition check passed: {}", #check_expr);
|
||
})
|
||
} else {
|
||
Ok(quote! {
|
||
// 非严格模式:返回错误
|
||
if !(#check_tokens) {
|
||
log::error!("Precondition check failed: {}", #check_expr);
|
||
return Err(ConstitutionalError::PreconditionFailed(#error_message.to_string()).into());
|
||
}
|
||
log::debug!("Precondition check passed: {}", #check_expr);
|
||
})
|
||
}
|
||
}
|
||
|
||
/// 生成义务记录代码
|
||
pub fn generate_obligation_record(
|
||
clause_id: &str,
|
||
obligation_type: &str,
|
||
function_name: &Ident,
|
||
) -> proc_macro2::TokenStream {
|
||
quote! {
|
||
// 记录宪法义务
|
||
nac_constitution_state::record_obligation(
|
||
#clause_id,
|
||
#obligation_type,
|
||
stringify!(#function_name),
|
||
&format!("{:?}", std::any::type_name::<Self>())
|
||
);
|
||
|
||
log::info!(
|
||
"Constitutional obligation recorded: clause={}, type={}, function={}",
|
||
#clause_id,
|
||
#obligation_type,
|
||
stringify!(#function_name)
|
||
);
|
||
}
|
||
}
|
||
|
||
/// 生成元数据注册代码
|
||
pub fn generate_metadata_registration(
|
||
metadata: &FunctionMetadata,
|
||
) -> proc_macro2::TokenStream {
|
||
let clause_id = metadata.clause_id;
|
||
let function_name = metadata.function_name;
|
||
let inputs = metadata.inputs;
|
||
let output = metadata.output;
|
||
let check_expression = metadata.check_expression;
|
||
let obligation_type = metadata.obligation_type;
|
||
|
||
quote! {
|
||
// 注册函数元数据到全局注册表
|
||
#[doc(hidden)]
|
||
#[allow(non_upper_case_globals)]
|
||
const _: () = {
|
||
#[used]
|
||
#[link_section = ".constitutional_metadata"]
|
||
static METADATA: nac_constitution_macros::FunctionMetadata =
|
||
nac_constitution_macros::FunctionMetadata {
|
||
clause_id: #clause_id,
|
||
function_name: #function_name,
|
||
inputs: #inputs,
|
||
output: #output,
|
||
check_expression: #check_expression,
|
||
obligation_type: #obligation_type,
|
||
};
|
||
};
|
||
}
|
||
}
|
||
|
||
/// 生成日志记录代码
|
||
pub fn generate_logging(
|
||
clause_id: &str,
|
||
function_name: &Ident,
|
||
log_level: &str,
|
||
) -> proc_macro2::TokenStream {
|
||
match log_level {
|
||
"trace" => quote! {
|
||
log::trace!("Constitutional function invoked: clause={}, function={}", #clause_id, stringify!(#function_name));
|
||
},
|
||
"debug" => quote! {
|
||
log::debug!("Constitutional function invoked: clause={}, function={}", #clause_id, stringify!(#function_name));
|
||
},
|
||
"info" => quote! {
|
||
log::info!("Constitutional function invoked: clause={}, function={}", #clause_id, stringify!(#function_name));
|
||
},
|
||
_ => quote! {
|
||
log::trace!("Constitutional function invoked: clause={}, function={}", #clause_id, stringify!(#function_name));
|
||
},
|
||
}
|
||
}
|
||
|
||
/// 生成错误处理代码
|
||
pub fn generate_error_handling(
|
||
function_name: &Ident,
|
||
error_type: Option<&Type>,
|
||
) -> proc_macro2::TokenStream {
|
||
if let Some(err_ty) = error_type {
|
||
quote! {
|
||
.map_err(|e: #err_ty| {
|
||
log::error!("Constitutional function failed: function={}, error={:?}", stringify!(#function_name), e);
|
||
e
|
||
})
|
||
}
|
||
} else {
|
||
quote! {
|
||
.map_err(|e| {
|
||
log::error!("Constitutional function failed: function={}, error={:?}", stringify!(#function_name), e);
|
||
e
|
||
})
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 测试生成器
|
||
pub struct TestGenerator;
|
||
|
||
impl TestGenerator {
|
||
/// 生成单元测试代码
|
||
pub fn generate_unit_tests(
|
||
function: &ItemFn,
|
||
clause_id: &str,
|
||
) -> proc_macro2::TokenStream {
|
||
let fn_name = &function.sig.ident;
|
||
let test_name = syn::Ident::new(
|
||
&format!("test_{}_constitutional_check", fn_name),
|
||
fn_name.span(),
|
||
);
|
||
|
||
quote! {
|
||
#[cfg(test)]
|
||
mod constitutional_tests {
|
||
use super::*;
|
||
|
||
#[test]
|
||
fn #test_name() {
|
||
// 测试宪法条款检查
|
||
let clause = nac_constitution_state::get_clause(#clause_id);
|
||
assert!(clause.is_some(), "Constitutional clause '{}' should exist", #clause_id);
|
||
|
||
let clause = clause.unwrap();
|
||
assert!(clause.is_active(), "Constitutional clause '{}' should be active", #clause_id);
|
||
}
|
||
|
||
#[test]
|
||
fn test_precondition_validation() {
|
||
// 测试前置条件验证
|
||
// TODO: 添加具体的前置条件测试
|
||
}
|
||
|
||
#[test]
|
||
fn test_obligation_recording() {
|
||
// 测试义务记录
|
||
// TODO: 添加义务记录测试
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 生成集成测试代码
|
||
pub fn generate_integration_tests(
|
||
metadata: &ClauseMetadata,
|
||
) -> proc_macro2::TokenStream {
|
||
let clause_id = &metadata.id;
|
||
let test_mod_name = syn::Ident::new(
|
||
&format!("integration_tests_{}", clause_id.to_lowercase().replace("-", "_")),
|
||
proc_macro2::Span::call_site(),
|
||
);
|
||
|
||
quote! {
|
||
#[cfg(test)]
|
||
mod #test_mod_name {
|
||
use super::*;
|
||
|
||
#[test]
|
||
fn test_clause_lifecycle() {
|
||
// 测试条款生命周期
|
||
let clause = nac_constitution_state::get_clause(#clause_id);
|
||
assert!(clause.is_some());
|
||
}
|
||
|
||
#[test]
|
||
fn test_clause_parameters() {
|
||
// 测试条款参数
|
||
let clause = nac_constitution_state::get_clause(#clause_id).unwrap();
|
||
// TODO: 验证参数值
|
||
}
|
||
|
||
#[test]
|
||
fn test_clause_functions() {
|
||
// 测试条款关联函数
|
||
// TODO: 调用并验证所有关联函数
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 生成边界测试代码
|
||
pub fn generate_boundary_tests(
|
||
function_name: &Ident,
|
||
param_name: &str,
|
||
min_value: Option<&str>,
|
||
max_value: Option<&str>,
|
||
) -> proc_macro2::TokenStream {
|
||
let test_name = syn::Ident::new(
|
||
&format!("test_{}_boundary_{}", function_name, param_name),
|
||
function_name.span(),
|
||
);
|
||
|
||
let min_test = if let Some(min) = min_value {
|
||
let min_tokens: proc_macro2::TokenStream = min.parse().unwrap();
|
||
quote! {
|
||
// 测试最小边界
|
||
let result = #function_name(#min_tokens - 1);
|
||
assert!(result.is_err(), "Should fail with value below minimum");
|
||
|
||
let result = #function_name(#min_tokens);
|
||
assert!(result.is_ok(), "Should succeed with minimum value");
|
||
}
|
||
} else {
|
||
quote! {}
|
||
};
|
||
|
||
let max_test = if let Some(max) = max_value {
|
||
let max_tokens: proc_macro2::TokenStream = max.parse().unwrap();
|
||
quote! {
|
||
// 测试最大边界
|
||
let result = #function_name(#max_tokens);
|
||
assert!(result.is_ok(), "Should succeed with maximum value");
|
||
|
||
let result = #function_name(#max_tokens + 1);
|
||
assert!(result.is_err(), "Should fail with value above maximum");
|
||
}
|
||
} else {
|
||
quote! {}
|
||
};
|
||
|
||
quote! {
|
||
#[cfg(test)]
|
||
#[test]
|
||
fn #test_name() {
|
||
#min_test
|
||
#max_test
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 文档生成器
|
||
pub struct DocGenerator;
|
||
|
||
impl DocGenerator {
|
||
/// 生成函数文档
|
||
pub fn generate_function_doc(
|
||
metadata: &FunctionMetadata,
|
||
) -> String {
|
||
let mut doc = String::new();
|
||
|
||
doc.push_str(&format!("# Constitutional Function: {}\n\n", metadata.function_name));
|
||
doc.push_str(&format!("**Clause ID**: `{}`\n\n", metadata.clause_id));
|
||
doc.push_str(&format!("**Signature**: `{}({}) -> {}`\n\n",
|
||
metadata.function_name, metadata.inputs, metadata.output));
|
||
|
||
if !metadata.check_expression.is_empty() {
|
||
doc.push_str(&format!("**Precondition**: `{}`\n\n", metadata.check_expression));
|
||
}
|
||
|
||
if !metadata.obligation_type.is_empty() {
|
||
doc.push_str(&format!("**Obligation**: `{}`\n\n", metadata.obligation_type));
|
||
}
|
||
|
||
doc.push_str("## Description\n\n");
|
||
doc.push_str("This function is subject to constitutional constraints and validation.\n\n");
|
||
|
||
doc.push_str("## Constitutional Checks\n\n");
|
||
doc.push_str("1. Verifies that the constitutional clause exists and is active\n");
|
||
doc.push_str("2. Validates preconditions before execution\n");
|
||
doc.push_str("3. Records constitutional obligations\n");
|
||
doc.push_str("4. Logs function invocation and completion\n\n");
|
||
|
||
doc
|
||
}
|
||
|
||
/// 生成条款文档
|
||
pub fn generate_clause_doc(
|
||
metadata: &ClauseMetadata,
|
||
) -> String {
|
||
let mut doc = String::new();
|
||
|
||
doc.push_str(&format!("# Constitutional Clause: {}\n\n", metadata.name));
|
||
doc.push_str(&format!("**ID**: `{}`\n\n", metadata.id));
|
||
doc.push_str(&format!("**Version**: `{}`\n\n", metadata.version));
|
||
doc.push_str(&format!("**Description**: {}\n\n", metadata.description));
|
||
|
||
if !metadata.parameters.is_empty() {
|
||
doc.push_str("## Parameters\n\n");
|
||
for (name, param) in &metadata.parameters {
|
||
doc.push_str(&format!("- **{}** (`{}`): {}\n", name, param.param_type, param.description));
|
||
if let Some(default) = ¶m.default_value {
|
||
doc.push_str(&format!(" - Default: `{}`\n", default));
|
||
}
|
||
if let Some(min) = ¶m.min_value {
|
||
doc.push_str(&format!(" - Minimum: `{}`\n", min));
|
||
}
|
||
if let Some(max) = ¶m.max_value {
|
||
doc.push_str(&format!(" - Maximum: `{}`\n", max));
|
||
}
|
||
}
|
||
doc.push_str("\n");
|
||
}
|
||
|
||
if !metadata.functions.is_empty() {
|
||
doc.push_str("## Associated Functions\n\n");
|
||
for func in &metadata.functions {
|
||
doc.push_str(&format!("- `{}`\n", func));
|
||
}
|
||
doc.push_str("\n");
|
||
}
|
||
|
||
doc.push_str(&format!("**Created**: {}\n", metadata.created_at));
|
||
doc.push_str(&format!("**Updated**: {}\n", metadata.updated_at));
|
||
|
||
doc
|
||
}
|
||
|
||
/// 生成API文档
|
||
pub fn generate_api_doc(
|
||
functions: &[FunctionMetadata],
|
||
clauses: &[ClauseMetadata],
|
||
) -> String {
|
||
let mut doc = String::new();
|
||
|
||
doc.push_str("# NAC Constitutional API Documentation\n\n");
|
||
doc.push_str("This document provides comprehensive documentation for all constitutional functions and clauses.\n\n");
|
||
|
||
doc.push_str("## Constitutional Clauses\n\n");
|
||
for clause in clauses {
|
||
doc.push_str(&Self::generate_clause_doc(clause));
|
||
doc.push_str("\n---\n\n");
|
||
}
|
||
|
||
doc.push_str("## Constitutional Functions\n\n");
|
||
for func in functions {
|
||
doc.push_str(&Self::generate_function_doc(func));
|
||
doc.push_str("\n---\n\n");
|
||
}
|
||
|
||
doc
|
||
}
|
||
}
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
#[test]
|
||
fn test_generate_constitutional_check() {
|
||
let code = CodeGenerator::generate_constitutional_check("TEST_CLAUSE", false);
|
||
let code_str = quote::quote!(#code).to_string();
|
||
assert!(code_str.contains("TEST_CLAUSE"));
|
||
assert!(code_str.contains("get_clause"));
|
||
}
|
||
|
||
#[test]
|
||
fn test_generate_precondition_check() {
|
||
let code = CodeGenerator::generate_precondition_check(
|
||
"amount > 0",
|
||
"Amount must be positive",
|
||
false
|
||
).unwrap();
|
||
let code_str = quote::quote!(#code).to_string();
|
||
assert!(code_str.contains("amount > 0"));
|
||
}
|
||
|
||
#[test]
|
||
fn test_generate_function_doc() {
|
||
let metadata = FunctionMetadata::new(
|
||
"TEST_CLAUSE",
|
||
"test_function",
|
||
"amount: u64",
|
||
"Result<(), Error>",
|
||
"amount > 0",
|
||
"test_obligation",
|
||
);
|
||
|
||
let doc = DocGenerator::generate_function_doc(&metadata);
|
||
assert!(doc.contains("Constitutional Function"));
|
||
assert!(doc.contains("TEST_CLAUSE"));
|
||
assert!(doc.contains("test_function"));
|
||
}
|
||
}
|