#![cfg_attr(coverage_nightly, coverage(off))]
use anyhow::Result;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::path::Path;
use super::types::{MemoryAnalysis, WasmComplexity, WasmMetrics};
use crate::models::unified_ast::{AstDag, Language};
pub struct ParsedAst {
pub language: Language,
pub dag: AstDag,
pub source_file: Option<std::path::PathBuf>,
pub parse_errors: Vec<String>,
pub metadata: std::collections::HashMap<String, String>,
}
#[async_trait]
pub trait LanguageParser: Send + Sync {
fn parse_content(&self, content: &str, path: Option<&Path>) -> Result<ParsedAst>;
fn language(&self) -> Language;
}
#[async_trait]
pub trait WasmAwareParser: LanguageParser {
fn extract_wasm_metrics(&self, ast: &AstDag) -> Result<WasmMetrics>;
fn analyze_memory_patterns(&self, ast: &AstDag) -> Result<MemoryAnalysis>;
fn calculate_wasm_complexity(&self, ast: &AstDag) -> Result<WasmComplexity>;
fn capabilities(&self) -> WasmAnalysisCapabilities {
WasmAnalysisCapabilities::default()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WasmAnalysisCapabilities {
pub memory_analysis: bool,
pub gas_estimation: bool,
pub security_analysis: bool,
pub optimization_hints: bool,
pub streaming_support: bool,
pub simd_analysis: bool,
pub multi_memory: bool,
pub max_file_size: usize,
}
impl Default for WasmAnalysisCapabilities {
fn default() -> Self {
Self {
memory_analysis: true,
gas_estimation: true,
security_analysis: true,
optimization_hints: true,
streaming_support: true,
simd_analysis: false,
multi_memory: false,
max_file_size: 100 * 1_024 * 1_024, }
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod property_tests {
use proptest::prelude::*;
proptest! {
#[test]
fn basic_property_stability(_input in ".*") {
prop_assert!(true);
}
#[test]
fn module_consistency_check(_x in 0u32..1000) {
prop_assert!(_x < 1001);
}
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashMap;
#[test]
fn test_parsed_ast_creation() {
let ast = ParsedAst {
language: Language::Rust,
dag: AstDag::default(),
source_file: Some(std::path::PathBuf::from("/test/file.rs")),
parse_errors: vec!["error1".to_string()],
metadata: HashMap::new(),
};
assert_eq!(ast.language, Language::Rust);
assert!(ast.source_file.is_some());
assert_eq!(ast.parse_errors.len(), 1);
}
#[test]
fn test_parsed_ast_no_source_file() {
let ast = ParsedAst {
language: Language::TypeScript,
dag: AstDag::default(),
source_file: None,
parse_errors: vec![],
metadata: HashMap::from([("key".to_string(), "value".to_string())]),
};
assert_eq!(ast.language, Language::TypeScript);
assert!(ast.source_file.is_none());
assert!(ast.parse_errors.is_empty());
assert_eq!(ast.metadata.get("key"), Some(&"value".to_string()));
}
#[test]
fn test_wasm_analysis_capabilities_default() {
let caps = WasmAnalysisCapabilities::default();
assert!(caps.memory_analysis);
assert!(caps.gas_estimation);
assert!(caps.security_analysis);
assert!(caps.optimization_hints);
assert!(caps.streaming_support);
assert!(!caps.simd_analysis);
assert!(!caps.multi_memory);
assert_eq!(caps.max_file_size, 100 * 1024 * 1024);
}
#[test]
fn test_wasm_analysis_capabilities_clone() {
let caps = WasmAnalysisCapabilities::default();
let cloned = caps.clone();
assert_eq!(caps.memory_analysis, cloned.memory_analysis);
assert_eq!(caps.max_file_size, cloned.max_file_size);
}
#[test]
fn test_wasm_analysis_capabilities_debug() {
let caps = WasmAnalysisCapabilities::default();
let debug_str = format!("{:?}", caps);
assert!(debug_str.contains("WasmAnalysisCapabilities"));
assert!(debug_str.contains("memory_analysis"));
}
#[test]
fn test_wasm_analysis_capabilities_serialization() {
let caps = WasmAnalysisCapabilities {
memory_analysis: false,
gas_estimation: true,
security_analysis: false,
optimization_hints: true,
streaming_support: false,
simd_analysis: true,
multi_memory: true,
max_file_size: 50 * 1024 * 1024,
};
let json = serde_json::to_string(&caps).unwrap();
assert!(json.contains("\"memory_analysis\":false"));
assert!(json.contains("\"simd_analysis\":true"));
let deserialized: WasmAnalysisCapabilities = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized.memory_analysis, false);
assert_eq!(deserialized.simd_analysis, true);
assert_eq!(deserialized.max_file_size, 50 * 1024 * 1024);
}
#[test]
fn test_wasm_analysis_capabilities_custom_values() {
let caps = WasmAnalysisCapabilities {
memory_analysis: true,
gas_estimation: false,
security_analysis: true,
optimization_hints: false,
streaming_support: true,
simd_analysis: true,
multi_memory: true,
max_file_size: 1024,
};
assert!(caps.memory_analysis);
assert!(!caps.gas_estimation);
assert!(caps.simd_analysis);
assert!(caps.multi_memory);
assert_eq!(caps.max_file_size, 1024);
}
}