Skip to main content

depyler_annotations/
lib.rs

1#![allow(clippy::missing_errors_doc)] // Parse methods have obvious error conditions
2
3use regex::Regex;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6use thiserror::Error;
7
8#[derive(Error, Debug)]
9pub enum AnnotationError {
10    #[error("Invalid annotation syntax: {0}")]
11    InvalidSyntax(String),
12    #[error("Unknown annotation key: {0}")]
13    UnknownKey(String),
14    #[error("Invalid value for key {key}: {value}")]
15    InvalidValue { key: String, value: String },
16}
17
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
19#[allow(clippy::struct_excessive_bools)] // Configuration struct requires multiple boolean flags
20pub struct TranspilationAnnotations {
21    pub type_strategy: TypeStrategy,
22    pub ownership_model: OwnershipModel,
23    pub safety_level: SafetyLevel,
24    pub performance_hints: Vec<PerformanceHint>,
25    pub fallback_strategy: FallbackStrategy,
26    pub bounds_checking: BoundsChecking,
27    pub optimization_level: OptimizationLevel,
28    pub thread_safety: ThreadSafety,
29    pub interior_mutability: InteriorMutability,
30    pub string_strategy: StringStrategy,
31    pub hash_strategy: HashStrategy,
32    pub panic_behavior: PanicBehavior,
33    pub error_strategy: ErrorStrategy,
34    pub global_strategy: GlobalStrategy,
35    pub termination: Termination,
36    pub invariants: Vec<String>,
37    pub verify_bounds: bool,
38    pub service_type: Option<ServiceType>,
39    pub migration_strategy: Option<MigrationStrategy>,
40    pub compatibility_layer: Option<CompatibilityLayer>,
41    pub pattern: Option<String>,
42    // Lambda-specific annotations
43    pub lambda_annotations: Option<LambdaAnnotations>,
44    pub custom_attributes: Vec<String>,
45}
46
47impl Default for TranspilationAnnotations {
48    fn default() -> Self {
49        Self {
50            type_strategy: TypeStrategy::Conservative,
51            ownership_model: OwnershipModel::Owned,
52            safety_level: SafetyLevel::Safe,
53            performance_hints: Vec::new(),
54            fallback_strategy: FallbackStrategy::Error,
55            bounds_checking: BoundsChecking::Explicit,
56            optimization_level: OptimizationLevel::Standard,
57            thread_safety: ThreadSafety::NotRequired,
58            interior_mutability: InteriorMutability::None,
59            string_strategy: StringStrategy::Conservative,
60            hash_strategy: HashStrategy::Standard,
61            panic_behavior: PanicBehavior::Propagate,
62            error_strategy: ErrorStrategy::Panic,
63            global_strategy: GlobalStrategy::None,
64            termination: Termination::Unknown,
65            invariants: Vec::new(),
66            verify_bounds: false,
67            service_type: None,
68            migration_strategy: None,
69            compatibility_layer: None,
70            pattern: None,
71            lambda_annotations: None,
72            custom_attributes: Vec::new(),
73        }
74    }
75}
76
77#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
78#[allow(clippy::struct_excessive_bools)] // Lambda configuration requires many boolean flags
79pub struct LambdaAnnotations {
80    pub runtime: LambdaRuntime,
81    pub event_type: Option<LambdaEventType>,
82    pub cold_start_optimize: bool,
83    pub memory_size: u16,
84    pub architecture: Architecture,
85    pub pre_warm_paths: Vec<String>,
86    pub custom_serialization: bool,
87    pub batch_failure_reporting: bool,
88    pub timeout: Option<u16>,
89    pub tracing_enabled: bool,
90    pub environment_variables: Vec<(String, String)>,
91}
92
93impl Default for LambdaAnnotations {
94    fn default() -> Self {
95        Self {
96            runtime: LambdaRuntime::ProvidedAl2,
97            event_type: None,
98            cold_start_optimize: true,
99            memory_size: 128,
100            architecture: Architecture::Arm64,
101            pre_warm_paths: vec![],
102            custom_serialization: false,
103            batch_failure_reporting: false,
104            timeout: None,
105            tracing_enabled: false,
106            environment_variables: vec![],
107        }
108    }
109}
110
111#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
112pub enum LambdaRuntime {
113    ProvidedAl2,
114    ProvidedAl2023,
115    Custom(String),
116}
117
118#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
119pub enum LambdaEventType {
120    Auto,
121    S3Event,
122    ApiGatewayProxyRequest,
123    ApiGatewayV2HttpRequest,
124    SqsEvent,
125    SnsEvent,
126    DynamodbEvent,
127    EventBridgeEvent(Option<String>),
128    CloudwatchEvent,
129    KinesisEvent,
130    Custom(String),
131}
132
133#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
134pub enum Architecture {
135    X86_64,
136    Arm64,
137}
138
139#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
140pub enum TypeStrategy {
141    Conservative,
142    Aggressive,
143    ZeroCopy,
144    AlwaysOwned,
145}
146
147#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
148pub enum OwnershipModel {
149    Owned,
150    Borrowed,
151    Shared,
152}
153
154#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
155pub enum SafetyLevel {
156    Safe,
157    UnsafeAllowed,
158}
159
160#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
161pub enum PerformanceHint {
162    Vectorize,
163    UnrollLoops(u32),
164    OptimizeForLatency,
165    OptimizeForThroughput,
166    PerformanceCritical,
167}
168
169#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
170pub enum FallbackStrategy {
171    Mcp,
172    Manual,
173    Error,
174}
175
176#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
177pub enum BoundsChecking {
178    Explicit,
179    Implicit,
180    Disabled,
181}
182
183#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
184pub enum OptimizationLevel {
185    Standard,
186    Aggressive,
187    Conservative,
188}
189
190#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
191pub enum ThreadSafety {
192    Required,
193    NotRequired,
194}
195
196#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
197pub enum InteriorMutability {
198    None,
199    ArcMutex,
200    RefCell,
201    Cell,
202}
203
204#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
205pub enum StringStrategy {
206    Conservative,
207    AlwaysOwned,
208    ZeroCopy,
209}
210
211#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
212pub enum HashStrategy {
213    Standard,
214    Fnv,
215    AHash,
216}
217
218#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
219pub enum PanicBehavior {
220    Propagate,
221    ReturnError,
222    Abort,
223}
224
225#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
226pub enum ErrorStrategy {
227    Panic,
228    ResultType,
229    OptionType,
230}
231
232#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
233pub enum GlobalStrategy {
234    None,
235    LazyStatic,
236    OnceCell,
237}
238
239#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
240pub enum Termination {
241    Unknown,
242    Proven,
243    BoundedLoop(u32),
244}
245
246#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
247pub enum ServiceType {
248    WebApi,
249    Cli,
250    Library,
251}
252
253#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
254pub enum MigrationStrategy {
255    Incremental,
256    BigBang,
257    Hybrid,
258}
259
260#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
261pub enum CompatibilityLayer {
262    PyO3,
263    CTypes,
264    None,
265}
266
267pub struct AnnotationParser {
268    pattern: Regex,
269}
270
271#[derive(Debug, Clone, Default)]
272pub struct AnnotationValidator;
273
274impl AnnotationValidator {
275    /// Creates a new annotation validator.
276    pub fn new() -> Self {
277        Self
278    }
279
280    /// Validates the consistency of annotation settings.
281    ///
282    /// # Errors
283    ///
284    /// Returns a vector of error messages if any validation rules are violated.
285    pub fn validate(&self, annotations: &TranspilationAnnotations) -> Result<(), Vec<String>> {
286        let mut errors = Vec::new();
287
288        // Validate conflicting strategies
289        if annotations.string_strategy == StringStrategy::ZeroCopy
290            && annotations.ownership_model == OwnershipModel::Owned
291        {
292            errors
293                .push("Zero-copy string strategy conflicts with owned ownership model".to_string());
294        }
295
296        if annotations.thread_safety == ThreadSafety::Required
297            && annotations.interior_mutability == InteriorMutability::RefCell
298        {
299            errors.push("RefCell is not thread-safe, use Arc<Mutex<T>> instead".to_string());
300        }
301
302        if annotations.panic_behavior == PanicBehavior::ReturnError
303            && annotations.error_strategy == ErrorStrategy::Panic
304        {
305            errors.push("Conflicting panic behavior and error strategy".to_string());
306        }
307
308        if annotations.optimization_level == OptimizationLevel::Aggressive
309            && annotations.bounds_checking == BoundsChecking::Explicit
310        {
311            errors.push(
312                "Aggressive optimization may conflict with explicit bounds checking".to_string(),
313            );
314        }
315
316        if errors.is_empty() {
317            Ok(())
318        } else {
319            Err(errors)
320        }
321    }
322
323    pub fn suggest_improvements(&self, annotations: &TranspilationAnnotations) -> Vec<String> {
324        let mut suggestions = Vec::new();
325
326        if annotations
327            .performance_hints
328            .contains(&PerformanceHint::PerformanceCritical)
329            && annotations.optimization_level != OptimizationLevel::Aggressive
330        {
331            suggestions.push(
332                "Consider using optimization_level = \"aggressive\" for performance critical code"
333                    .to_string(),
334            );
335        }
336
337        if annotations.thread_safety == ThreadSafety::Required
338            && annotations.ownership_model != OwnershipModel::Shared
339        {
340            suggestions
341                .push("Consider using ownership = \"shared\" for thread-safe code".to_string());
342        }
343
344        if annotations.service_type == Some(ServiceType::WebApi)
345            && !annotations
346                .performance_hints
347                .contains(&PerformanceHint::OptimizeForLatency)
348        {
349            suggestions
350                .push("Consider adding optimization_hint = \"latency\" for web APIs".to_string());
351        }
352
353        suggestions
354    }
355}
356
357#[derive(Debug, Clone)]
358pub struct AnnotationExtractor {
359    function_pattern: Regex,
360    class_pattern: Regex,
361}
362
363impl Default for AnnotationExtractor {
364    fn default() -> Self {
365        Self {
366            function_pattern: Regex::new(r"(?m)^def\s+(\w+)\s*\(").expect("static regex"),
367            class_pattern: Regex::new(r"(?m)^class\s+(\w+)\s*[\(:]").expect("static regex"),
368        }
369    }
370}
371
372impl AnnotationExtractor {
373    /// Creates a new annotation extractor with pre-compiled regex patterns.
374    pub fn new() -> Self {
375        Self::default()
376    }
377
378    /// Extracts annotations for a specific function from source code.
379    ///
380    /// # Panics
381    ///
382    /// Panics if regex patterns fail to match (should not happen with valid regex).
383    pub fn extract_function_annotations(
384        &self,
385        source: &str,
386        function_name: &str,
387    ) -> Option<String> {
388        let lines: Vec<&str> = source.lines().collect();
389
390        for (i, line) in lines.iter().enumerate() {
391            if let Some(captures) = self.function_pattern.captures(line) {
392                if captures.get(1).expect("capture group 1 exists").as_str() == function_name {
393                    // Collect annotations above the function
394                    let mut annotations = Vec::new();
395                    let mut j = i.saturating_sub(1);
396
397                    while j < i && (lines[j].trim().starts_with('#') || lines[j].trim().is_empty())
398                    {
399                        if lines[j].contains("@depyler:") {
400                            annotations.push(lines[j]);
401                        }
402                        if j == 0 {
403                            break;
404                        }
405                        j = j.saturating_sub(1);
406                    }
407
408                    if !annotations.is_empty() {
409                        annotations.reverse();
410                        return Some(annotations.join("\n"));
411                    }
412                }
413            }
414        }
415        None
416    }
417
418    /// Extracts annotations for a specific class from source code.
419    ///
420    /// # Panics
421    ///
422    /// Panics if regex patterns fail to match (should not happen with valid regex).
423    pub fn extract_class_annotations(&self, source: &str, class_name: &str) -> Option<String> {
424        let lines: Vec<&str> = source.lines().collect();
425
426        for (i, line) in lines.iter().enumerate() {
427            if let Some(captures) = self.class_pattern.captures(line) {
428                if captures.get(1).expect("capture group 1 exists").as_str() == class_name {
429                    // Collect annotations above the class
430                    let mut annotations = Vec::new();
431                    let mut j = i.saturating_sub(1);
432
433                    while j < i && (lines[j].trim().starts_with('#') || lines[j].trim().is_empty())
434                    {
435                        if lines[j].contains("@depyler:") {
436                            annotations.push(lines[j]);
437                        }
438                        if j == 0 {
439                            break;
440                        }
441                        j = j.saturating_sub(1);
442                    }
443
444                    if !annotations.is_empty() {
445                        annotations.reverse();
446                        return Some(annotations.join("\n"));
447                    }
448                }
449            }
450        }
451        None
452    }
453}
454
455impl Default for AnnotationParser {
456    fn default() -> Self {
457        Self::new()
458    }
459}
460
461impl AnnotationParser {
462    /// Creates a new annotation parser.
463    ///
464    /// # Panics
465    ///
466    /// Panics if the internal regex pattern fails to compile (should never happen).
467    pub fn new() -> Self {
468        let pattern =
469            // This regex is statically known to be valid
470            Regex::new(r"#\s*@depyler:\s*(\w+)\s*=\s*(.+)")
471                .unwrap_or_else(|e| panic!("Failed to compile annotation regex: {e}"));
472        Self { pattern }
473    }
474
475    /// Parses annotations from source code comments.
476    ///
477    /// # Errors
478    ///
479    /// Returns `AnnotationError` if unknown keys or invalid values are encountered.
480    ///
481    /// # Panics
482    ///
483    /// Panics if the regex fails to capture groups (should not happen with valid regex).
484    pub fn parse_annotations(
485        &self,
486        source: &str,
487    ) -> Result<TranspilationAnnotations, AnnotationError> {
488        let mut annotations = TranspilationAnnotations::default();
489        let mut parsed_values: HashMap<String, String> = HashMap::new();
490
491        for line in source.lines() {
492            if let Some(captures) = self.pattern.captures(line) {
493                let key = captures
494                    .get(1)
495                    .expect("capture group 1 exists")
496                    .as_str()
497                    .to_string();
498                let value = captures
499                    .get(2)
500                    .expect("capture group 2 exists")
501                    .as_str()
502                    .trim_matches('"')
503                    .trim();
504
505                // Special handling for custom_attribute - accumulate instead of replace
506                if key == "custom_attribute" {
507                    annotations.custom_attributes.push(value.to_string());
508                } else {
509                    parsed_values.insert(key, value.to_string());
510                }
511            }
512        }
513
514        self.apply_annotations(&mut annotations, parsed_values)?;
515        Ok(annotations)
516    }
517
518    /// Parses annotations from function-specific source code.
519    ///
520    /// # Errors
521    ///
522    /// Returns `AnnotationError` if parsing fails.
523    pub fn parse_function_annotations(
524        &self,
525        function_source: &str,
526    ) -> Result<TranspilationAnnotations, AnnotationError> {
527        self.parse_annotations(function_source)
528    }
529
530    fn apply_annotations(
531        &self,
532        annotations: &mut TranspilationAnnotations,
533        values: HashMap<String, String>,
534    ) -> Result<(), AnnotationError> {
535        for (key, value) in values {
536            // Dispatch to category handlers
537            match key.as_str() {
538                // Core annotations (5)
539                "type_strategy" | "ownership" | "safety_level" | "fallback" | "bounds_checking" => {
540                    self.apply_core_annotation(annotations, &key, &value)?;
541                }
542
543                // Optimization annotations (5)
544                "optimization_level"
545                | "performance_critical"
546                | "vectorize"
547                | "unroll_loops"
548                | "optimization_hint" => {
549                    self.apply_optimization_annotation(annotations, &key, &value)?;
550                }
551
552                // Thread safety annotations (2)
553                "thread_safety" | "interior_mutability" => {
554                    self.apply_thread_safety_annotation(annotations, &key, &value)?;
555                }
556
557                // String/Hash strategy (2)
558                "string_strategy" | "hash_strategy" => {
559                    self.apply_string_hash_annotation(annotations, &key, &value)?;
560                }
561
562                // Error handling (2)
563                "panic_behavior" | "error_strategy" => {
564                    self.apply_error_handling_annotation(annotations, &key, &value)?;
565                }
566
567                // Global strategy (1)
568                "global_strategy" => {
569                    self.apply_global_strategy_annotation(annotations, &value)?;
570                }
571
572                // Verification (3)
573                "termination" | "invariant" | "verify_bounds" => {
574                    self.apply_verification_annotation(annotations, &key, &value)?;
575                }
576
577                // Service metadata (4)
578                "service_type" | "migration_strategy" | "compatibility_layer" | "pattern" => {
579                    self.apply_service_metadata_annotation(annotations, &key, &value)?;
580                }
581
582                // Lambda-specific annotations (9)
583                "lambda_runtime"
584                | "event_type"
585                | "cold_start_optimize"
586                | "memory_size"
587                | "architecture"
588                | "batch_failure_reporting"
589                | "custom_serialization"
590                | "timeout"
591                | "tracing" => {
592                    self.apply_lambda_annotation(annotations, &key, &value)?;
593                }
594
595                _ => return Err(AnnotationError::UnknownKey(key)),
596            }
597        }
598        Ok(())
599    }
600
601    /// Apply core annotation (type_strategy, ownership, safety_level, fallback, bounds_checking)
602    #[inline]
603    fn apply_core_annotation(
604        &self,
605        annotations: &mut TranspilationAnnotations,
606        key: &str,
607        value: &str,
608    ) -> Result<(), AnnotationError> {
609        match key {
610            "type_strategy" => {
611                annotations.type_strategy = self.parse_type_strategy(value)?;
612            }
613            "ownership" => {
614                annotations.ownership_model = self.parse_ownership_model(value)?;
615            }
616            "safety_level" => {
617                annotations.safety_level = self.parse_safety_level(value)?;
618            }
619            "fallback" => {
620                annotations.fallback_strategy = self.parse_fallback_strategy(value)?;
621            }
622            "bounds_checking" => {
623                annotations.bounds_checking = self.parse_bounds_checking(value)?;
624            }
625            _ => unreachable!("apply_core_annotation called with non-core key"),
626        }
627        Ok(())
628    }
629
630    /// Apply optimization annotation (optimization_level, performance_critical, vectorize, unroll_loops, optimization_hint)
631    #[inline]
632    fn apply_optimization_annotation(
633        &self,
634        annotations: &mut TranspilationAnnotations,
635        key: &str,
636        value: &str,
637    ) -> Result<(), AnnotationError> {
638        match key {
639            "optimization_level" => {
640                annotations.optimization_level = self.parse_optimization_level(value)?;
641            }
642            "performance_critical" => {
643                if value == "true" {
644                    annotations
645                        .performance_hints
646                        .push(PerformanceHint::PerformanceCritical);
647                }
648            }
649            "vectorize" => {
650                if value == "true" {
651                    annotations
652                        .performance_hints
653                        .push(PerformanceHint::Vectorize);
654                }
655            }
656            "unroll_loops" => {
657                let count: u32 = value.parse().map_err(|_| AnnotationError::InvalidValue {
658                    key: key.to_string(),
659                    value: value.to_string(),
660                })?;
661                annotations
662                    .performance_hints
663                    .push(PerformanceHint::UnrollLoops(count));
664            }
665            "optimization_hint" => {
666                self.apply_optimization_hint(annotations, value)?;
667            }
668            _ => unreachable!("apply_optimization_annotation called with non-optimization key"),
669        }
670        Ok(())
671    }
672
673    /// Apply optimization hint sub-handler
674    #[inline]
675    fn apply_optimization_hint(
676        &self,
677        annotations: &mut TranspilationAnnotations,
678        value: &str,
679    ) -> Result<(), AnnotationError> {
680        match value {
681            "vectorize" => annotations
682                .performance_hints
683                .push(PerformanceHint::Vectorize),
684            "latency" => annotations
685                .performance_hints
686                .push(PerformanceHint::OptimizeForLatency),
687            "throughput" => annotations
688                .performance_hints
689                .push(PerformanceHint::OptimizeForThroughput),
690            "async_ready" => {
691                eprintln!("Warning: async_ready is experimental and not yet fully supported");
692            }
693            _ => {
694                return Err(AnnotationError::InvalidValue {
695                    key: "optimization_hint".to_string(),
696                    value: value.to_string(),
697                })
698            }
699        }
700        Ok(())
701    }
702
703    /// Apply thread safety annotation (thread_safety, interior_mutability)
704    #[inline]
705    fn apply_thread_safety_annotation(
706        &self,
707        annotations: &mut TranspilationAnnotations,
708        key: &str,
709        value: &str,
710    ) -> Result<(), AnnotationError> {
711        match key {
712            "thread_safety" => {
713                annotations.thread_safety = self.parse_thread_safety(value)?;
714            }
715            "interior_mutability" => {
716                annotations.interior_mutability = self.parse_interior_mutability(value)?;
717            }
718            _ => unreachable!("apply_thread_safety_annotation called with non-thread-safety key"),
719        }
720        Ok(())
721    }
722
723    /// Apply global strategy annotation
724    #[inline]
725    fn apply_global_strategy_annotation(
726        &self,
727        annotations: &mut TranspilationAnnotations,
728        value: &str,
729    ) -> Result<(), AnnotationError> {
730        annotations.global_strategy = self.parse_global_strategy(value)?;
731        Ok(())
732    }
733
734    /// Apply string/hash strategy annotation (string_strategy, hash_strategy)
735    #[inline]
736    fn apply_string_hash_annotation(
737        &self,
738        annotations: &mut TranspilationAnnotations,
739        key: &str,
740        value: &str,
741    ) -> Result<(), AnnotationError> {
742        match key {
743            "string_strategy" => {
744                annotations.string_strategy = self.parse_string_strategy(value)?;
745            }
746            "hash_strategy" => {
747                annotations.hash_strategy = self.parse_hash_strategy(value)?;
748            }
749            _ => unreachable!("apply_string_hash_annotation called with non-string/hash key"),
750        }
751        Ok(())
752    }
753
754    /// Apply error handling annotation (panic_behavior, error_strategy)
755    #[inline]
756    fn apply_error_handling_annotation(
757        &self,
758        annotations: &mut TranspilationAnnotations,
759        key: &str,
760        value: &str,
761    ) -> Result<(), AnnotationError> {
762        match key {
763            "panic_behavior" => {
764                annotations.panic_behavior = self.parse_panic_behavior(value)?;
765            }
766            "error_strategy" => {
767                annotations.error_strategy = self.parse_error_strategy(value)?;
768            }
769            _ => unreachable!("apply_error_handling_annotation called with non-error key"),
770        }
771        Ok(())
772    }
773
774    /// Apply verification annotation (termination, invariant, verify_bounds)
775    #[inline]
776    fn apply_verification_annotation(
777        &self,
778        annotations: &mut TranspilationAnnotations,
779        key: &str,
780        value: &str,
781    ) -> Result<(), AnnotationError> {
782        match key {
783            "termination" => {
784                annotations.termination = self.parse_termination(value)?;
785            }
786            "invariant" => {
787                annotations.invariants.push(value.to_string());
788            }
789            "verify_bounds" => {
790                annotations.verify_bounds = value == "true";
791            }
792            _ => unreachable!("apply_verification_annotation called with non-verification key"),
793        }
794        Ok(())
795    }
796
797    /// Apply service metadata annotation (service_type, migration_strategy, compatibility_layer, pattern)
798    #[inline]
799    fn apply_service_metadata_annotation(
800        &self,
801        annotations: &mut TranspilationAnnotations,
802        key: &str,
803        value: &str,
804    ) -> Result<(), AnnotationError> {
805        match key {
806            "service_type" => {
807                annotations.service_type = Some(self.parse_service_type(value)?);
808            }
809            "migration_strategy" => {
810                annotations.migration_strategy = Some(self.parse_migration_strategy(value)?);
811            }
812            "compatibility_layer" => {
813                annotations.compatibility_layer = Some(self.parse_compatibility_layer(value)?);
814            }
815            "pattern" => {
816                annotations.pattern = Some(value.to_string());
817            }
818            _ => unreachable!("apply_service_metadata_annotation called with non-service key"),
819        }
820        Ok(())
821    }
822
823    /// Apply lambda-specific annotation (9 lambda keys) - dispatcher with ≤10 complexity
824    #[inline]
825    fn apply_lambda_annotation(
826        &self,
827        annotations: &mut TranspilationAnnotations,
828        key: &str,
829        value: &str,
830    ) -> Result<(), AnnotationError> {
831        let lambda_annotations = annotations
832            .lambda_annotations
833            .get_or_insert_with(LambdaAnnotations::default);
834
835        match key {
836            "lambda_runtime" | "event_type" | "architecture" => {
837                self.apply_lambda_config(lambda_annotations, key, value)?;
838            }
839            "cold_start_optimize"
840            | "batch_failure_reporting"
841            | "custom_serialization"
842            | "tracing" => {
843                self.apply_lambda_flags(lambda_annotations, key, value);
844            }
845            "memory_size" | "timeout" => {
846                self.apply_lambda_numeric(lambda_annotations, key, value)?;
847            }
848            _ => unreachable!("apply_lambda_annotation called with non-lambda key"),
849        }
850        Ok(())
851    }
852
853    /// Apply lambda configuration (runtime, event_type, architecture)
854    #[inline]
855    fn apply_lambda_config(
856        &self,
857        lambda_annotations: &mut LambdaAnnotations,
858        key: &str,
859        value: &str,
860    ) -> Result<(), AnnotationError> {
861        match key {
862            "lambda_runtime" => {
863                lambda_annotations.runtime = self.parse_lambda_runtime(value)?;
864            }
865            "event_type" => {
866                lambda_annotations.event_type = Some(self.parse_lambda_event_type(value)?);
867            }
868            "architecture" => {
869                lambda_annotations.architecture = self.parse_architecture(value)?;
870            }
871            _ => unreachable!("apply_lambda_config called with non-config key"),
872        }
873        Ok(())
874    }
875
876    /// Apply lambda feature flags (cold_start_optimize, batch_failure_reporting, custom_serialization, tracing)
877    #[inline]
878    fn apply_lambda_flags(
879        &self,
880        lambda_annotations: &mut LambdaAnnotations,
881        key: &str,
882        value: &str,
883    ) {
884        match key {
885            "cold_start_optimize" => {
886                lambda_annotations.cold_start_optimize = value == "true";
887            }
888            "batch_failure_reporting" => {
889                lambda_annotations.batch_failure_reporting = value == "true";
890            }
891            "custom_serialization" => {
892                lambda_annotations.custom_serialization = value == "true";
893            }
894            "tracing" => {
895                lambda_annotations.tracing_enabled = value == "true" || value == "Active";
896            }
897            _ => unreachable!("apply_lambda_flags called with non-flag key"),
898        }
899    }
900
901    /// Apply lambda numeric settings (memory_size, timeout)
902    #[inline]
903    fn apply_lambda_numeric(
904        &self,
905        lambda_annotations: &mut LambdaAnnotations,
906        key: &str,
907        value: &str,
908    ) -> Result<(), AnnotationError> {
909        match key {
910            "memory_size" => {
911                lambda_annotations.memory_size =
912                    value.parse().map_err(|_| AnnotationError::InvalidValue {
913                        key: key.to_string(),
914                        value: value.to_string(),
915                    })?;
916            }
917            "timeout" => {
918                lambda_annotations.timeout =
919                    Some(value.parse().map_err(|_| AnnotationError::InvalidValue {
920                        key: key.to_string(),
921                        value: value.to_string(),
922                    })?);
923            }
924            _ => unreachable!("apply_lambda_numeric called with non-numeric key"),
925        }
926        Ok(())
927    }
928
929    fn parse_type_strategy(&self, value: &str) -> Result<TypeStrategy, AnnotationError> {
930        match value {
931            "conservative" => Ok(TypeStrategy::Conservative),
932            "aggressive" => Ok(TypeStrategy::Aggressive),
933            "zero_copy" => Ok(TypeStrategy::ZeroCopy),
934            "always_owned" => Ok(TypeStrategy::AlwaysOwned),
935            _ => Err(AnnotationError::InvalidValue {
936                key: "type_strategy".to_string(),
937                value: value.to_string(),
938            }),
939        }
940    }
941
942    fn parse_ownership_model(&self, value: &str) -> Result<OwnershipModel, AnnotationError> {
943        match value {
944            "owned" => Ok(OwnershipModel::Owned),
945            "borrowed" => Ok(OwnershipModel::Borrowed),
946            "shared" => Ok(OwnershipModel::Shared),
947            _ => Err(AnnotationError::InvalidValue {
948                key: "ownership".to_string(),
949                value: value.to_string(),
950            }),
951        }
952    }
953
954    fn parse_safety_level(&self, value: &str) -> Result<SafetyLevel, AnnotationError> {
955        match value {
956            "safe" => Ok(SafetyLevel::Safe),
957            "unsafe_allowed" => Ok(SafetyLevel::UnsafeAllowed),
958            _ => Err(AnnotationError::InvalidValue {
959                key: "safety_level".to_string(),
960                value: value.to_string(),
961            }),
962        }
963    }
964
965    fn parse_fallback_strategy(&self, value: &str) -> Result<FallbackStrategy, AnnotationError> {
966        match value {
967            "mcp" => Ok(FallbackStrategy::Mcp),
968            "manual" => Ok(FallbackStrategy::Manual),
969            "error" => Ok(FallbackStrategy::Error),
970            _ => Err(AnnotationError::InvalidValue {
971                key: "fallback".to_string(),
972                value: value.to_string(),
973            }),
974        }
975    }
976
977    fn parse_bounds_checking(&self, value: &str) -> Result<BoundsChecking, AnnotationError> {
978        match value {
979            "explicit" => Ok(BoundsChecking::Explicit),
980            "implicit" => Ok(BoundsChecking::Implicit),
981            "disabled" => Ok(BoundsChecking::Disabled),
982            _ => Err(AnnotationError::InvalidValue {
983                key: "bounds_checking".to_string(),
984                value: value.to_string(),
985            }),
986        }
987    }
988
989    fn parse_optimization_level(&self, value: &str) -> Result<OptimizationLevel, AnnotationError> {
990        match value {
991            "standard" => Ok(OptimizationLevel::Standard),
992            "aggressive" => Ok(OptimizationLevel::Aggressive),
993            "conservative" => Ok(OptimizationLevel::Conservative),
994            _ => Err(AnnotationError::InvalidValue {
995                key: "optimization_level".to_string(),
996                value: value.to_string(),
997            }),
998        }
999    }
1000
1001    fn parse_thread_safety(&self, value: &str) -> Result<ThreadSafety, AnnotationError> {
1002        match value {
1003            "required" => Ok(ThreadSafety::Required),
1004            "not_required" => Ok(ThreadSafety::NotRequired),
1005            _ => Err(AnnotationError::InvalidValue {
1006                key: "thread_safety".to_string(),
1007                value: value.to_string(),
1008            }),
1009        }
1010    }
1011
1012    fn parse_interior_mutability(
1013        &self,
1014        value: &str,
1015    ) -> Result<InteriorMutability, AnnotationError> {
1016        match value {
1017            "none" => Ok(InteriorMutability::None),
1018            "arc_mutex" => Ok(InteriorMutability::ArcMutex),
1019            "ref_cell" => Ok(InteriorMutability::RefCell),
1020            "cell" => Ok(InteriorMutability::Cell),
1021            _ => Err(AnnotationError::InvalidValue {
1022                key: "interior_mutability".to_string(),
1023                value: value.to_string(),
1024            }),
1025        }
1026    }
1027
1028    fn parse_string_strategy(&self, value: &str) -> Result<StringStrategy, AnnotationError> {
1029        match value {
1030            "conservative" => Ok(StringStrategy::Conservative),
1031            "always_owned" => Ok(StringStrategy::AlwaysOwned),
1032            "zero_copy" => Ok(StringStrategy::ZeroCopy),
1033            _ => Err(AnnotationError::InvalidValue {
1034                key: "string_strategy".to_string(),
1035                value: value.to_string(),
1036            }),
1037        }
1038    }
1039
1040    fn parse_hash_strategy(&self, value: &str) -> Result<HashStrategy, AnnotationError> {
1041        match value {
1042            "standard" => Ok(HashStrategy::Standard),
1043            "fnv" => Ok(HashStrategy::Fnv),
1044            "ahash" => Ok(HashStrategy::AHash),
1045            _ => Err(AnnotationError::InvalidValue {
1046                key: "hash_strategy".to_string(),
1047                value: value.to_string(),
1048            }),
1049        }
1050    }
1051
1052    fn parse_panic_behavior(&self, value: &str) -> Result<PanicBehavior, AnnotationError> {
1053        match value {
1054            "propagate" => Ok(PanicBehavior::Propagate),
1055            "return_error" => Ok(PanicBehavior::ReturnError),
1056            "abort" => Ok(PanicBehavior::Abort),
1057            _ => Err(AnnotationError::InvalidValue {
1058                key: "panic_behavior".to_string(),
1059                value: value.to_string(),
1060            }),
1061        }
1062    }
1063
1064    fn parse_error_strategy(&self, value: &str) -> Result<ErrorStrategy, AnnotationError> {
1065        match value {
1066            "panic" => Ok(ErrorStrategy::Panic),
1067            "result_type" => Ok(ErrorStrategy::ResultType),
1068            "option_type" => Ok(ErrorStrategy::OptionType),
1069            _ => Err(AnnotationError::InvalidValue {
1070                key: "error_strategy".to_string(),
1071                value: value.to_string(),
1072            }),
1073        }
1074    }
1075
1076    fn parse_global_strategy(&self, value: &str) -> Result<GlobalStrategy, AnnotationError> {
1077        match value {
1078            "none" => Ok(GlobalStrategy::None),
1079            "lazy_static" => Ok(GlobalStrategy::LazyStatic),
1080            "once_cell" => Ok(GlobalStrategy::OnceCell),
1081            _ => Err(AnnotationError::InvalidValue {
1082                key: "global_strategy".to_string(),
1083                value: value.to_string(),
1084            }),
1085        }
1086    }
1087
1088    fn parse_termination(&self, value: &str) -> Result<Termination, AnnotationError> {
1089        match value {
1090            "unknown" => Ok(Termination::Unknown),
1091            "proven" => Ok(Termination::Proven),
1092            _ => {
1093                if value.starts_with("bounded_") {
1094                    if let Some(num_str) = value.strip_prefix("bounded_") {
1095                        if let Ok(bound) = num_str.parse::<u32>() {
1096                            return Ok(Termination::BoundedLoop(bound));
1097                        }
1098                    }
1099                }
1100                Err(AnnotationError::InvalidValue {
1101                    key: "termination".to_string(),
1102                    value: value.to_string(),
1103                })
1104            }
1105        }
1106    }
1107
1108    fn parse_service_type(&self, value: &str) -> Result<ServiceType, AnnotationError> {
1109        match value {
1110            "web_api" => Ok(ServiceType::WebApi),
1111            "cli" => Ok(ServiceType::Cli),
1112            "library" => Ok(ServiceType::Library),
1113            _ => Err(AnnotationError::InvalidValue {
1114                key: "service_type".to_string(),
1115                value: value.to_string(),
1116            }),
1117        }
1118    }
1119
1120    fn parse_migration_strategy(&self, value: &str) -> Result<MigrationStrategy, AnnotationError> {
1121        match value {
1122            "incremental" => Ok(MigrationStrategy::Incremental),
1123            "big_bang" => Ok(MigrationStrategy::BigBang),
1124            "hybrid" => Ok(MigrationStrategy::Hybrid),
1125            _ => Err(AnnotationError::InvalidValue {
1126                key: "migration_strategy".to_string(),
1127                value: value.to_string(),
1128            }),
1129        }
1130    }
1131
1132    fn parse_compatibility_layer(
1133        &self,
1134        value: &str,
1135    ) -> Result<CompatibilityLayer, AnnotationError> {
1136        match value {
1137            "pyo3" => Ok(CompatibilityLayer::PyO3),
1138            "ctypes" => Ok(CompatibilityLayer::CTypes),
1139            "none" => Ok(CompatibilityLayer::None),
1140            _ => Err(AnnotationError::InvalidValue {
1141                key: "compatibility_layer".to_string(),
1142                value: value.to_string(),
1143            }),
1144        }
1145    }
1146
1147    fn parse_lambda_runtime(&self, value: &str) -> Result<LambdaRuntime, AnnotationError> {
1148        match value {
1149            "provided.al2" => Ok(LambdaRuntime::ProvidedAl2),
1150            "provided.al2023" => Ok(LambdaRuntime::ProvidedAl2023),
1151            _ => Ok(LambdaRuntime::Custom(value.to_string())),
1152        }
1153    }
1154
1155    fn parse_lambda_event_type(&self, value: &str) -> Result<LambdaEventType, AnnotationError> {
1156        // Quick path for common types
1157        let event_type = match value {
1158            "auto" => LambdaEventType::Auto,
1159            "S3Event" | "SqsEvent" | "SnsEvent" | "DynamodbEvent" | "CloudwatchEvent"
1160            | "KinesisEvent" => self.parse_aws_service_event(value),
1161            "APIGatewayProxyRequest" | "APIGatewayV2HttpRequest" => {
1162                self.parse_api_gateway_event(value)
1163            }
1164            _ => self.parse_custom_event_type(value),
1165        };
1166        Ok(event_type)
1167    }
1168
1169    /// Parse AWS service events (S3, SQS, SNS, DynamoDB, CloudWatch, Kinesis)
1170    #[inline]
1171    fn parse_aws_service_event(&self, value: &str) -> LambdaEventType {
1172        match value {
1173            "S3Event" => LambdaEventType::S3Event,
1174            "SqsEvent" => LambdaEventType::SqsEvent,
1175            "SnsEvent" => LambdaEventType::SnsEvent,
1176            "DynamodbEvent" => LambdaEventType::DynamodbEvent,
1177            "CloudwatchEvent" => LambdaEventType::CloudwatchEvent,
1178            "KinesisEvent" => LambdaEventType::KinesisEvent,
1179            _ => unreachable!("parse_aws_service_event called with non-AWS-service event"),
1180        }
1181    }
1182
1183    /// Parse API Gateway events (v1 and v2)
1184    #[inline]
1185    fn parse_api_gateway_event(&self, value: &str) -> LambdaEventType {
1186        match value {
1187            "APIGatewayProxyRequest" => LambdaEventType::ApiGatewayProxyRequest,
1188            "APIGatewayV2HttpRequest" => LambdaEventType::ApiGatewayV2HttpRequest,
1189            _ => unreachable!("parse_api_gateway_event called with non-API-Gateway event"),
1190        }
1191    }
1192
1193    /// Parse custom or EventBridge event types
1194    #[inline]
1195    fn parse_custom_event_type(&self, value: &str) -> LambdaEventType {
1196        if value.starts_with("EventBridgeEvent<") && value.ends_with('>') {
1197            let inner = &value[17..value.len() - 1];
1198            LambdaEventType::EventBridgeEvent(Some(inner.to_string()))
1199        } else if value == "EventBridgeEvent" {
1200            LambdaEventType::EventBridgeEvent(None)
1201        } else {
1202            LambdaEventType::Custom(value.to_string())
1203        }
1204    }
1205
1206    fn parse_architecture(&self, value: &str) -> Result<Architecture, AnnotationError> {
1207        match value {
1208            "x86_64" | "x64" => Ok(Architecture::X86_64),
1209            "arm64" | "aarch64" => Ok(Architecture::Arm64),
1210            _ => Err(AnnotationError::InvalidValue {
1211                key: "architecture".to_string(),
1212                value: value.to_string(),
1213            }),
1214        }
1215    }
1216}
1217
1218#[cfg(test)]
1219mod tests {
1220    use super::*;
1221
1222    // ===================================================================
1223    // Default Implementation Tests
1224    // ===================================================================
1225
1226    #[test]
1227    fn test_default_annotations() {
1228        let annotations = TranspilationAnnotations::default();
1229        assert_eq!(annotations.type_strategy, TypeStrategy::Conservative);
1230        assert_eq!(annotations.ownership_model, OwnershipModel::Owned);
1231        assert_eq!(annotations.safety_level, SafetyLevel::Safe);
1232        assert_eq!(annotations.fallback_strategy, FallbackStrategy::Error);
1233    }
1234
1235    #[test]
1236    fn test_default_annotations_all_fields() {
1237        let a = TranspilationAnnotations::default();
1238        assert_eq!(a.bounds_checking, BoundsChecking::Explicit);
1239        assert_eq!(a.optimization_level, OptimizationLevel::Standard);
1240        assert_eq!(a.thread_safety, ThreadSafety::NotRequired);
1241        assert_eq!(a.interior_mutability, InteriorMutability::None);
1242        assert_eq!(a.string_strategy, StringStrategy::Conservative);
1243        assert_eq!(a.hash_strategy, HashStrategy::Standard);
1244        assert_eq!(a.panic_behavior, PanicBehavior::Propagate);
1245        assert_eq!(a.error_strategy, ErrorStrategy::Panic);
1246        assert_eq!(a.global_strategy, GlobalStrategy::None);
1247        assert_eq!(a.termination, Termination::Unknown);
1248        assert!(a.invariants.is_empty());
1249        assert!(!a.verify_bounds);
1250        assert!(a.service_type.is_none());
1251        assert!(a.migration_strategy.is_none());
1252        assert!(a.compatibility_layer.is_none());
1253        assert!(a.pattern.is_none());
1254        assert!(a.lambda_annotations.is_none());
1255        assert!(a.custom_attributes.is_empty());
1256        assert!(a.performance_hints.is_empty());
1257    }
1258
1259    #[test]
1260    fn test_default_lambda_annotations() {
1261        let la = LambdaAnnotations::default();
1262        assert_eq!(la.runtime, LambdaRuntime::ProvidedAl2);
1263        assert!(la.event_type.is_none());
1264        assert!(la.cold_start_optimize);
1265        assert_eq!(la.memory_size, 128);
1266        assert_eq!(la.architecture, Architecture::Arm64);
1267        assert!(la.pre_warm_paths.is_empty());
1268        assert!(!la.custom_serialization);
1269        assert!(!la.batch_failure_reporting);
1270        assert!(la.timeout.is_none());
1271        assert!(!la.tracing_enabled);
1272        assert!(la.environment_variables.is_empty());
1273    }
1274
1275    #[test]
1276    fn test_annotation_validator_default() {
1277        let v = AnnotationValidator;
1278        let a = TranspilationAnnotations::default();
1279        assert!(v.validate(&a).is_ok());
1280    }
1281
1282    #[test]
1283    fn test_annotation_extractor_default() {
1284        let e = AnnotationExtractor::default();
1285        let result = e.extract_function_annotations("def foo():\n    pass", "foo");
1286        assert!(result.is_none());
1287    }
1288
1289    #[test]
1290    fn test_annotation_parser_default() {
1291        let p = AnnotationParser::default();
1292        let a = p.parse_annotations("# no annotations here").unwrap();
1293        assert_eq!(a, TranspilationAnnotations::default());
1294    }
1295
1296    // ===================================================================
1297    // Core Parser Tests
1298    // ===================================================================
1299
1300    #[test]
1301    fn test_parse_basic_annotations() {
1302        let parser = AnnotationParser::new();
1303        let source = r#"
1304# @depyler: type_strategy = "conservative"
1305# @depyler: ownership = "borrowed"
1306def test_function():
1307    pass
1308        "#;
1309
1310        let annotations = parser.parse_annotations(source).unwrap();
1311        assert_eq!(annotations.type_strategy, TypeStrategy::Conservative);
1312        assert_eq!(annotations.ownership_model, OwnershipModel::Borrowed);
1313    }
1314
1315    #[test]
1316    fn test_parse_empty_source() {
1317        let parser = AnnotationParser::new();
1318        let annotations = parser.parse_annotations("").unwrap();
1319        assert_eq!(annotations, TranspilationAnnotations::default());
1320    }
1321
1322    #[test]
1323    fn test_parse_no_annotations_in_source() {
1324        let parser = AnnotationParser::new();
1325        let source = "def foo():\n    return 42\n";
1326        let annotations = parser.parse_annotations(source).unwrap();
1327        assert_eq!(annotations, TranspilationAnnotations::default());
1328    }
1329
1330    #[test]
1331    fn test_parse_function_annotations_delegates() {
1332        let parser = AnnotationParser::new();
1333        let source = "# @depyler: ownership = \"shared\"\ndef foo(): pass";
1334        let a = parser.parse_function_annotations(source).unwrap();
1335        assert_eq!(a.ownership_model, OwnershipModel::Shared);
1336    }
1337
1338    // ===================================================================
1339    // Type Strategy Parser Tests
1340    // ===================================================================
1341
1342    #[test]
1343    fn test_parse_type_strategy_all_variants() {
1344        let parser = AnnotationParser::new();
1345        let cases = [
1346            ("conservative", TypeStrategy::Conservative),
1347            ("aggressive", TypeStrategy::Aggressive),
1348            ("zero_copy", TypeStrategy::ZeroCopy),
1349            ("always_owned", TypeStrategy::AlwaysOwned),
1350        ];
1351        for (input, expected) in &cases {
1352            let source = format!("# @depyler: type_strategy = \"{input}\"");
1353            let a = parser.parse_annotations(&source).unwrap();
1354            assert_eq!(a.type_strategy, *expected);
1355        }
1356    }
1357
1358    #[test]
1359    fn test_parse_type_strategy_invalid() {
1360        let parser = AnnotationParser::new();
1361        let source = "# @depyler: type_strategy = \"bogus\"";
1362        let result = parser.parse_annotations(source);
1363        assert!(matches!(result, Err(AnnotationError::InvalidValue { .. })));
1364    }
1365
1366    // ===================================================================
1367    // Ownership Model Parser Tests
1368    // ===================================================================
1369
1370    #[test]
1371    fn test_parse_ownership_model_all_variants() {
1372        let parser = AnnotationParser::new();
1373        let cases = [
1374            ("owned", OwnershipModel::Owned),
1375            ("borrowed", OwnershipModel::Borrowed),
1376            ("shared", OwnershipModel::Shared),
1377        ];
1378        for (input, expected) in &cases {
1379            let source = format!("# @depyler: ownership = \"{input}\"");
1380            let a = parser.parse_annotations(&source).unwrap();
1381            assert_eq!(a.ownership_model, *expected);
1382        }
1383    }
1384
1385    #[test]
1386    fn test_parse_ownership_invalid() {
1387        let parser = AnnotationParser::new();
1388        let source = "# @depyler: ownership = \"moved\"";
1389        let result = parser.parse_annotations(source);
1390        assert!(matches!(result, Err(AnnotationError::InvalidValue { .. })));
1391    }
1392
1393    // ===================================================================
1394    // Safety Level Parser Tests
1395    // ===================================================================
1396
1397    #[test]
1398    fn test_parse_safety_annotations() {
1399        let parser = AnnotationParser::new();
1400        let source = r#"
1401# @depyler: safety_level = "unsafe_allowed"
1402# @depyler: bounds_checking = "disabled"
1403def unsafe_function():
1404    pass
1405        "#;
1406
1407        let annotations = parser.parse_annotations(source).unwrap();
1408        assert_eq!(annotations.safety_level, SafetyLevel::UnsafeAllowed);
1409        assert_eq!(annotations.bounds_checking, BoundsChecking::Disabled);
1410    }
1411
1412    #[test]
1413    fn test_parse_safety_level_safe() {
1414        let parser = AnnotationParser::new();
1415        let source = "# @depyler: safety_level = \"safe\"";
1416        let a = parser.parse_annotations(source).unwrap();
1417        assert_eq!(a.safety_level, SafetyLevel::Safe);
1418    }
1419
1420    #[test]
1421    fn test_parse_safety_level_invalid() {
1422        let parser = AnnotationParser::new();
1423        let source = "# @depyler: safety_level = \"yolo\"";
1424        let result = parser.parse_annotations(source);
1425        assert!(matches!(result, Err(AnnotationError::InvalidValue { .. })));
1426    }
1427
1428    // ===================================================================
1429    // Fallback Strategy Tests
1430    // ===================================================================
1431
1432    #[test]
1433    fn test_parse_fallback_strategy() {
1434        let parser = AnnotationParser::new();
1435        let source = r#"
1436# @depyler: fallback = "mcp"
1437def complex_function():
1438    pass
1439        "#;
1440
1441        let annotations = parser.parse_annotations(source).unwrap();
1442        assert_eq!(annotations.fallback_strategy, FallbackStrategy::Mcp);
1443    }
1444
1445    #[test]
1446    fn test_parse_fallback_all_variants() {
1447        let parser = AnnotationParser::new();
1448        let cases = [
1449            ("mcp", FallbackStrategy::Mcp),
1450            ("manual", FallbackStrategy::Manual),
1451            ("error", FallbackStrategy::Error),
1452        ];
1453        for (input, expected) in &cases {
1454            let source = format!("# @depyler: fallback = \"{input}\"");
1455            let a = parser.parse_annotations(&source).unwrap();
1456            assert_eq!(a.fallback_strategy, *expected);
1457        }
1458    }
1459
1460    #[test]
1461    fn test_parse_fallback_invalid() {
1462        let parser = AnnotationParser::new();
1463        let source = "# @depyler: fallback = \"skip\"";
1464        let result = parser.parse_annotations(source);
1465        assert!(matches!(result, Err(AnnotationError::InvalidValue { .. })));
1466    }
1467
1468    // ===================================================================
1469    // Bounds Checking Tests
1470    // ===================================================================
1471
1472    #[test]
1473    fn test_parse_bounds_checking_all_variants() {
1474        let parser = AnnotationParser::new();
1475        let cases = [
1476            ("explicit", BoundsChecking::Explicit),
1477            ("implicit", BoundsChecking::Implicit),
1478            ("disabled", BoundsChecking::Disabled),
1479        ];
1480        for (input, expected) in &cases {
1481            let source = format!("# @depyler: bounds_checking = \"{input}\"");
1482            let a = parser.parse_annotations(&source).unwrap();
1483            assert_eq!(a.bounds_checking, *expected);
1484        }
1485    }
1486
1487    // ===================================================================
1488    // Performance Hints Tests
1489    // ===================================================================
1490
1491    #[test]
1492    fn test_parse_performance_annotations() {
1493        let parser = AnnotationParser::new();
1494        let source = r#"
1495# @depyler: performance_critical = "true"
1496# @depyler: vectorize = "true"
1497# @depyler: unroll_loops = "4"
1498def fast_function():
1499    pass
1500        "#;
1501
1502        let annotations = parser.parse_annotations(source).unwrap();
1503        assert!(annotations
1504            .performance_hints
1505            .contains(&PerformanceHint::PerformanceCritical));
1506        assert!(annotations
1507            .performance_hints
1508            .contains(&PerformanceHint::Vectorize));
1509        assert!(annotations
1510            .performance_hints
1511            .contains(&PerformanceHint::UnrollLoops(4)));
1512    }
1513
1514    #[test]
1515    fn test_optimization_hints() {
1516        let parser = AnnotationParser::new();
1517        let source = r#"
1518# @depyler: optimization_hint = "vectorize"
1519# @depyler: optimization_level = "aggressive"
1520def optimized_function():
1521    pass
1522        "#;
1523
1524        let annotations = parser.parse_annotations(source).unwrap();
1525        assert!(annotations
1526            .performance_hints
1527            .contains(&PerformanceHint::Vectorize));
1528        assert_eq!(
1529            annotations.optimization_level,
1530            OptimizationLevel::Aggressive
1531        );
1532    }
1533
1534    #[test]
1535    fn test_parse_optimization_hint_latency() {
1536        let parser = AnnotationParser::new();
1537        let source = "# @depyler: optimization_hint = \"latency\"";
1538        let a = parser.parse_annotations(source).unwrap();
1539        assert!(a
1540            .performance_hints
1541            .contains(&PerformanceHint::OptimizeForLatency));
1542    }
1543
1544    #[test]
1545    fn test_parse_optimization_hint_throughput() {
1546        let parser = AnnotationParser::new();
1547        let source = "# @depyler: optimization_hint = \"throughput\"";
1548        let a = parser.parse_annotations(source).unwrap();
1549        assert!(a
1550            .performance_hints
1551            .contains(&PerformanceHint::OptimizeForThroughput));
1552    }
1553
1554    #[test]
1555    fn test_parse_optimization_hint_invalid() {
1556        let parser = AnnotationParser::new();
1557        let source = "# @depyler: optimization_hint = \"magic\"";
1558        let result = parser.parse_annotations(source);
1559        assert!(matches!(result, Err(AnnotationError::InvalidValue { .. })));
1560    }
1561
1562    #[test]
1563    fn test_parse_unroll_loops_invalid_value() {
1564        let parser = AnnotationParser::new();
1565        let source = "# @depyler: unroll_loops = \"not_a_number\"";
1566        let result = parser.parse_annotations(source);
1567        assert!(matches!(result, Err(AnnotationError::InvalidValue { .. })));
1568    }
1569
1570    #[test]
1571    fn test_parse_performance_critical_false() {
1572        let parser = AnnotationParser::new();
1573        let source = "# @depyler: performance_critical = \"false\"";
1574        let a = parser.parse_annotations(source).unwrap();
1575        assert!(!a
1576            .performance_hints
1577            .contains(&PerformanceHint::PerformanceCritical));
1578    }
1579
1580    #[test]
1581    fn test_parse_vectorize_false() {
1582        let parser = AnnotationParser::new();
1583        let source = "# @depyler: vectorize = \"false\"";
1584        let a = parser.parse_annotations(source).unwrap();
1585        assert!(!a
1586            .performance_hints
1587            .contains(&PerformanceHint::Vectorize));
1588    }
1589
1590    #[test]
1591    fn test_parse_optimization_level_all_variants() {
1592        let parser = AnnotationParser::new();
1593        let cases = [
1594            ("standard", OptimizationLevel::Standard),
1595            ("aggressive", OptimizationLevel::Aggressive),
1596            ("conservative", OptimizationLevel::Conservative),
1597        ];
1598        for (input, expected) in &cases {
1599            let source = format!("# @depyler: optimization_level = \"{input}\"");
1600            let a = parser.parse_annotations(&source).unwrap();
1601            assert_eq!(a.optimization_level, *expected);
1602        }
1603    }
1604
1605    // ===================================================================
1606    // Thread Safety Tests
1607    // ===================================================================
1608
1609    #[test]
1610    fn test_parse_thread_safety() {
1611        let parser = AnnotationParser::new();
1612        let source = r#"
1613# @depyler: thread_safety = "required"
1614# @depyler: interior_mutability = "arc_mutex"
1615def thread_safe_function():
1616    pass
1617        "#;
1618
1619        let annotations = parser.parse_annotations(source).unwrap();
1620        assert_eq!(annotations.thread_safety, ThreadSafety::Required);
1621        assert_eq!(
1622            annotations.interior_mutability,
1623            InteriorMutability::ArcMutex
1624        );
1625    }
1626
1627    #[test]
1628    fn test_parse_interior_mutability_all_variants() {
1629        let parser = AnnotationParser::new();
1630        let cases = [
1631            ("none", InteriorMutability::None),
1632            ("arc_mutex", InteriorMutability::ArcMutex),
1633            ("ref_cell", InteriorMutability::RefCell),
1634            ("cell", InteriorMutability::Cell),
1635        ];
1636        for (input, expected) in &cases {
1637            let source = format!("# @depyler: interior_mutability = \"{input}\"");
1638            let a = parser.parse_annotations(&source).unwrap();
1639            assert_eq!(a.interior_mutability, *expected);
1640        }
1641    }
1642
1643    #[test]
1644    fn test_parse_thread_safety_not_required() {
1645        let parser = AnnotationParser::new();
1646        let source = "# @depyler: thread_safety = \"not_required\"";
1647        let a = parser.parse_annotations(source).unwrap();
1648        assert_eq!(a.thread_safety, ThreadSafety::NotRequired);
1649    }
1650
1651    // ===================================================================
1652    // String and Hash Strategy Tests
1653    // ===================================================================
1654
1655    #[test]
1656    fn test_string_and_hash_strategies() {
1657        let parser = AnnotationParser::new();
1658        let source = r#"
1659# @depyler: string_strategy = "zero_copy"
1660# @depyler: hash_strategy = "fnv"
1661def string_function():
1662    pass
1663        "#;
1664
1665        let annotations = parser.parse_annotations(source).unwrap();
1666        assert_eq!(annotations.string_strategy, StringStrategy::ZeroCopy);
1667        assert_eq!(annotations.hash_strategy, HashStrategy::Fnv);
1668    }
1669
1670    #[test]
1671    fn test_parse_string_strategy_all_variants() {
1672        let parser = AnnotationParser::new();
1673        let cases = [
1674            ("conservative", StringStrategy::Conservative),
1675            ("always_owned", StringStrategy::AlwaysOwned),
1676            ("zero_copy", StringStrategy::ZeroCopy),
1677        ];
1678        for (input, expected) in &cases {
1679            let source = format!("# @depyler: string_strategy = \"{input}\"");
1680            let a = parser.parse_annotations(&source).unwrap();
1681            assert_eq!(a.string_strategy, *expected);
1682        }
1683    }
1684
1685    #[test]
1686    fn test_parse_hash_strategy_all_variants() {
1687        let parser = AnnotationParser::new();
1688        let cases = [
1689            ("standard", HashStrategy::Standard),
1690            ("fnv", HashStrategy::Fnv),
1691            ("ahash", HashStrategy::AHash),
1692        ];
1693        for (input, expected) in &cases {
1694            let source = format!("# @depyler: hash_strategy = \"{input}\"");
1695            let a = parser.parse_annotations(&source).unwrap();
1696            assert_eq!(a.hash_strategy, *expected);
1697        }
1698    }
1699
1700    // ===================================================================
1701    // Error Handling Annotations Tests
1702    // ===================================================================
1703
1704    #[test]
1705    fn test_error_handling_annotations() {
1706        let parser = AnnotationParser::new();
1707        let source = r#"
1708# @depyler: panic_behavior = "return_error"
1709# @depyler: error_strategy = "result_type"
1710def error_function():
1711    pass
1712        "#;
1713
1714        let annotations = parser.parse_annotations(source).unwrap();
1715        assert_eq!(annotations.panic_behavior, PanicBehavior::ReturnError);
1716        assert_eq!(annotations.error_strategy, ErrorStrategy::ResultType);
1717    }
1718
1719    #[test]
1720    fn test_parse_panic_behavior_all_variants() {
1721        let parser = AnnotationParser::new();
1722        let cases = [
1723            ("propagate", PanicBehavior::Propagate),
1724            ("return_error", PanicBehavior::ReturnError),
1725            ("abort", PanicBehavior::Abort),
1726        ];
1727        for (input, expected) in &cases {
1728            let source = format!("# @depyler: panic_behavior = \"{input}\"");
1729            let a = parser.parse_annotations(&source).unwrap();
1730            assert_eq!(a.panic_behavior, *expected);
1731        }
1732    }
1733
1734    #[test]
1735    fn test_parse_error_strategy_all_variants() {
1736        let parser = AnnotationParser::new();
1737        let cases = [
1738            ("panic", ErrorStrategy::Panic),
1739            ("result_type", ErrorStrategy::ResultType),
1740            ("option_type", ErrorStrategy::OptionType),
1741        ];
1742        for (input, expected) in &cases {
1743            let source = format!("# @depyler: error_strategy = \"{input}\"");
1744            let a = parser.parse_annotations(&source).unwrap();
1745            assert_eq!(a.error_strategy, *expected);
1746        }
1747    }
1748
1749    // ===================================================================
1750    // Global Strategy Tests
1751    // ===================================================================
1752
1753    #[test]
1754    fn test_global_strategy() {
1755        let parser = AnnotationParser::new();
1756        let source = r#"
1757# @depyler: global_strategy = "lazy_static"
1758def global_function():
1759    pass
1760        "#;
1761
1762        let annotations = parser.parse_annotations(source).unwrap();
1763        assert_eq!(annotations.global_strategy, GlobalStrategy::LazyStatic);
1764    }
1765
1766    #[test]
1767    fn test_parse_global_strategy_all_variants() {
1768        let parser = AnnotationParser::new();
1769        let cases = [
1770            ("none", GlobalStrategy::None),
1771            ("lazy_static", GlobalStrategy::LazyStatic),
1772            ("once_cell", GlobalStrategy::OnceCell),
1773        ];
1774        for (input, expected) in &cases {
1775            let source = format!("# @depyler: global_strategy = \"{input}\"");
1776            let a = parser.parse_annotations(&source).unwrap();
1777            assert_eq!(a.global_strategy, *expected);
1778        }
1779    }
1780
1781    // ===================================================================
1782    // Termination Tests
1783    // ===================================================================
1784
1785    #[test]
1786    fn test_parse_termination_unknown() {
1787        let parser = AnnotationParser::new();
1788        let source = "# @depyler: termination = \"unknown\"";
1789        let a = parser.parse_annotations(source).unwrap();
1790        assert_eq!(a.termination, Termination::Unknown);
1791    }
1792
1793    #[test]
1794    fn test_parse_termination_proven() {
1795        let parser = AnnotationParser::new();
1796        let source = "# @depyler: termination = \"proven\"";
1797        let a = parser.parse_annotations(source).unwrap();
1798        assert_eq!(a.termination, Termination::Proven);
1799    }
1800
1801    #[test]
1802    fn test_parse_termination_bounded_loop() {
1803        let parser = AnnotationParser::new();
1804        let source = "# @depyler: termination = \"bounded_100\"";
1805        let a = parser.parse_annotations(source).unwrap();
1806        assert_eq!(a.termination, Termination::BoundedLoop(100));
1807    }
1808
1809    #[test]
1810    fn test_parse_termination_bounded_loop_zero() {
1811        let parser = AnnotationParser::new();
1812        let source = "# @depyler: termination = \"bounded_0\"";
1813        let a = parser.parse_annotations(source).unwrap();
1814        assert_eq!(a.termination, Termination::BoundedLoop(0));
1815    }
1816
1817    #[test]
1818    fn test_parse_termination_invalid() {
1819        let parser = AnnotationParser::new();
1820        let source = "# @depyler: termination = \"infinite\"";
1821        let result = parser.parse_annotations(source);
1822        assert!(matches!(result, Err(AnnotationError::InvalidValue { .. })));
1823    }
1824
1825    #[test]
1826    fn test_parse_termination_bounded_non_numeric() {
1827        let parser = AnnotationParser::new();
1828        let source = "# @depyler: termination = \"bounded_abc\"";
1829        let result = parser.parse_annotations(source);
1830        assert!(matches!(result, Err(AnnotationError::InvalidValue { .. })));
1831    }
1832
1833    // ===================================================================
1834    // Verification Annotations Tests
1835    // ===================================================================
1836
1837    #[test]
1838    fn test_verification_annotations() {
1839        let parser = AnnotationParser::new();
1840        let source = r#"
1841# @depyler: termination = "proven"
1842# @depyler: invariant = "left <= right"
1843# @depyler: verify_bounds = "true"
1844def verified_function():
1845    pass
1846        "#;
1847
1848        let annotations = parser.parse_annotations(source).unwrap();
1849        assert_eq!(annotations.termination, Termination::Proven);
1850        assert!(annotations
1851            .invariants
1852            .contains(&"left <= right".to_string()));
1853        assert!(annotations.verify_bounds);
1854    }
1855
1856    #[test]
1857    fn test_parse_verify_bounds_false() {
1858        let parser = AnnotationParser::new();
1859        let source = "# @depyler: verify_bounds = \"false\"";
1860        let a = parser.parse_annotations(source).unwrap();
1861        assert!(!a.verify_bounds);
1862    }
1863
1864    // ===================================================================
1865    // Service and Migration Tests
1866    // ===================================================================
1867
1868    #[test]
1869    fn test_service_and_migration_annotations() {
1870        let parser = AnnotationParser::new();
1871        let source = r#"
1872# @depyler: service_type = "web_api"
1873# @depyler: migration_strategy = "incremental"
1874# @depyler: compatibility_layer = "pyo3"
1875def service_function():
1876    pass
1877        "#;
1878
1879        let annotations = parser.parse_annotations(source).unwrap();
1880        assert_eq!(annotations.service_type, Some(ServiceType::WebApi));
1881        assert_eq!(
1882            annotations.migration_strategy,
1883            Some(MigrationStrategy::Incremental)
1884        );
1885        assert_eq!(
1886            annotations.compatibility_layer,
1887            Some(CompatibilityLayer::PyO3)
1888        );
1889    }
1890
1891    #[test]
1892    fn test_parse_service_type_all_variants() {
1893        let parser = AnnotationParser::new();
1894        let cases = [
1895            ("web_api", ServiceType::WebApi),
1896            ("cli", ServiceType::Cli),
1897            ("library", ServiceType::Library),
1898        ];
1899        for (input, expected) in &cases {
1900            let source = format!("# @depyler: service_type = \"{input}\"");
1901            let a = parser.parse_annotations(&source).unwrap();
1902            assert_eq!(a.service_type, Some(expected.clone()));
1903        }
1904    }
1905
1906    #[test]
1907    fn test_parse_migration_strategy_all_variants() {
1908        let parser = AnnotationParser::new();
1909        let cases = [
1910            ("incremental", MigrationStrategy::Incremental),
1911            ("big_bang", MigrationStrategy::BigBang),
1912            ("hybrid", MigrationStrategy::Hybrid),
1913        ];
1914        for (input, expected) in &cases {
1915            let source = format!("# @depyler: migration_strategy = \"{input}\"");
1916            let a = parser.parse_annotations(&source).unwrap();
1917            assert_eq!(a.migration_strategy, Some(expected.clone()));
1918        }
1919    }
1920
1921    #[test]
1922    fn test_parse_compatibility_layer_all_variants() {
1923        let parser = AnnotationParser::new();
1924        let cases = [
1925            ("pyo3", CompatibilityLayer::PyO3),
1926            ("ctypes", CompatibilityLayer::CTypes),
1927            ("none", CompatibilityLayer::None),
1928        ];
1929        for (input, expected) in &cases {
1930            let source = format!("# @depyler: compatibility_layer = \"{input}\"");
1931            let a = parser.parse_annotations(&source).unwrap();
1932            assert_eq!(a.compatibility_layer, Some(expected.clone()));
1933        }
1934    }
1935
1936    #[test]
1937    fn test_parse_pattern_annotation() {
1938        let parser = AnnotationParser::new();
1939        let source = "# @depyler: pattern = \"observer\"";
1940        let a = parser.parse_annotations(source).unwrap();
1941        assert_eq!(a.pattern, Some("observer".to_string()));
1942    }
1943
1944    // ===================================================================
1945    // Error Type Tests
1946    // ===================================================================
1947
1948    #[test]
1949    fn test_invalid_annotation_key() {
1950        let parser = AnnotationParser::new();
1951        let source = r#"
1952# @depyler: invalid_key = "value"
1953def test_function():
1954    pass
1955        "#;
1956
1957        let result = parser.parse_annotations(source);
1958        assert!(matches!(result, Err(AnnotationError::UnknownKey(_))));
1959    }
1960
1961    #[test]
1962    fn test_invalid_annotation_value() {
1963        let parser = AnnotationParser::new();
1964        let source = r#"
1965# @depyler: type_strategy = "invalid_value"
1966def test_function():
1967    pass
1968        "#;
1969
1970        let result = parser.parse_annotations(source);
1971        assert!(matches!(result, Err(AnnotationError::InvalidValue { .. })));
1972    }
1973
1974    #[test]
1975    fn test_annotation_error_display_invalid_syntax() {
1976        let err = AnnotationError::InvalidSyntax("bad line".to_string());
1977        let msg = format!("{err}");
1978        assert!(msg.contains("Invalid annotation syntax"));
1979        assert!(msg.contains("bad line"));
1980    }
1981
1982    #[test]
1983    fn test_annotation_error_display_unknown_key() {
1984        let err = AnnotationError::UnknownKey("foo_bar".to_string());
1985        let msg = format!("{err}");
1986        assert!(msg.contains("Unknown annotation key"));
1987        assert!(msg.contains("foo_bar"));
1988    }
1989
1990    #[test]
1991    fn test_annotation_error_display_invalid_value() {
1992        let err = AnnotationError::InvalidValue {
1993            key: "type_strategy".to_string(),
1994            value: "bogus".to_string(),
1995        };
1996        let msg = format!("{err}");
1997        assert!(msg.contains("Invalid value for key type_strategy"));
1998        assert!(msg.contains("bogus"));
1999    }
2000
2001    #[test]
2002    fn test_annotation_error_is_debug() {
2003        let err = AnnotationError::UnknownKey("test".to_string());
2004        let debug = format!("{err:?}");
2005        assert!(debug.contains("UnknownKey"));
2006    }
2007
2008    // ===================================================================
2009    // Lambda Annotations Tests
2010    // ===================================================================
2011
2012    #[test]
2013    fn test_lambda_annotations_basic() {
2014        let parser = AnnotationParser::new();
2015        let source = r#"
2016# @depyler: lambda_runtime = "provided.al2"
2017# @depyler: event_type = "APIGatewayProxyRequest"
2018# @depyler: cold_start_optimize = "true"
2019def handler(event, context):
2020    pass
2021        "#;
2022
2023        let annotations = parser.parse_annotations(source).unwrap();
2024        assert!(annotations.lambda_annotations.is_some());
2025
2026        let lambda_annotations = annotations.lambda_annotations.unwrap();
2027        assert_eq!(lambda_annotations.runtime, LambdaRuntime::ProvidedAl2);
2028        assert_eq!(
2029            lambda_annotations.event_type,
2030            Some(LambdaEventType::ApiGatewayProxyRequest)
2031        );
2032        assert!(lambda_annotations.cold_start_optimize);
2033    }
2034
2035    #[test]
2036    fn test_lambda_annotations_memory_and_architecture() {
2037        let parser = AnnotationParser::new();
2038        let source = r#"
2039# @depyler: memory_size = "256"
2040# @depyler: architecture = "arm64"
2041# @depyler: timeout = "30"
2042def handler(event, context):
2043    pass
2044        "#;
2045
2046        let annotations = parser.parse_annotations(source).unwrap();
2047        let lambda_annotations = annotations.lambda_annotations.unwrap();
2048        assert_eq!(lambda_annotations.memory_size, 256);
2049        assert_eq!(lambda_annotations.architecture, Architecture::Arm64);
2050        assert_eq!(lambda_annotations.timeout, Some(30));
2051    }
2052
2053    #[test]
2054    fn test_lambda_eventbridge_with_custom_type() {
2055        let parser = AnnotationParser::new();
2056        let source = r#"
2057# @depyler: event_type = "EventBridgeEvent<OrderEvent>"
2058# @depyler: custom_serialization = "true"
2059def handler(event, context):
2060    pass
2061        "#;
2062
2063        let annotations = parser.parse_annotations(source).unwrap();
2064        let lambda_annotations = annotations.lambda_annotations.unwrap();
2065        assert_eq!(
2066            lambda_annotations.event_type,
2067            Some(LambdaEventType::EventBridgeEvent(Some(
2068                "OrderEvent".to_string()
2069            )))
2070        );
2071        assert!(lambda_annotations.custom_serialization);
2072    }
2073
2074    #[test]
2075    fn test_lambda_eventbridge_without_type_parameter() {
2076        let parser = AnnotationParser::new();
2077        let source = "# @depyler: event_type = \"EventBridgeEvent\"";
2078        let a = parser.parse_annotations(source).unwrap();
2079        let la = a.lambda_annotations.unwrap();
2080        assert_eq!(
2081            la.event_type,
2082            Some(LambdaEventType::EventBridgeEvent(None))
2083        );
2084    }
2085
2086    #[test]
2087    fn test_lambda_sqs_batch_processing() {
2088        let parser = AnnotationParser::new();
2089        let source = r#"
2090# @depyler: event_type = "SqsEvent"
2091# @depyler: batch_failure_reporting = "true"
2092# @depyler: tracing = "Active"
2093def handler(event, context):
2094    pass
2095        "#;
2096
2097        let annotations = parser.parse_annotations(source).unwrap();
2098        let lambda_annotations = annotations.lambda_annotations.unwrap();
2099        assert_eq!(
2100            lambda_annotations.event_type,
2101            Some(LambdaEventType::SqsEvent)
2102        );
2103        assert!(lambda_annotations.batch_failure_reporting);
2104        assert!(lambda_annotations.tracing_enabled);
2105    }
2106
2107    #[test]
2108    fn test_lambda_auto_event_type() {
2109        let parser = AnnotationParser::new();
2110        let source = r#"
2111# @depyler: event_type = "auto"
2112# @depyler: cold_start_optimize = "true"
2113def handler(event, context):
2114    pass
2115        "#;
2116
2117        let annotations = parser.parse_annotations(source).unwrap();
2118        let lambda_annotations = annotations.lambda_annotations.unwrap();
2119        assert_eq!(lambda_annotations.event_type, Some(LambdaEventType::Auto));
2120        assert!(lambda_annotations.cold_start_optimize);
2121    }
2122
2123    #[test]
2124    fn test_lambda_custom_runtime() {
2125        let parser = AnnotationParser::new();
2126        let source = r#"
2127# @depyler: lambda_runtime = "rust-runtime-1.0"
2128def handler(event, context):
2129    pass
2130        "#;
2131
2132        let annotations = parser.parse_annotations(source).unwrap();
2133        let lambda_annotations = annotations.lambda_annotations.unwrap();
2134        assert_eq!(
2135            lambda_annotations.runtime,
2136            LambdaRuntime::Custom("rust-runtime-1.0".to_string())
2137        );
2138    }
2139
2140    #[test]
2141    fn test_lambda_runtime_provided_al2023() {
2142        let parser = AnnotationParser::new();
2143        let source = "# @depyler: lambda_runtime = \"provided.al2023\"";
2144        let a = parser.parse_annotations(source).unwrap();
2145        let la = a.lambda_annotations.unwrap();
2146        assert_eq!(la.runtime, LambdaRuntime::ProvidedAl2023);
2147    }
2148
2149    #[test]
2150    fn test_lambda_architecture_x86_64() {
2151        let parser = AnnotationParser::new();
2152        let source = "# @depyler: architecture = \"x86_64\"";
2153        let a = parser.parse_annotations(source).unwrap();
2154        let la = a.lambda_annotations.unwrap();
2155        assert_eq!(la.architecture, Architecture::X86_64);
2156    }
2157
2158    #[test]
2159    fn test_lambda_architecture_x64_alias() {
2160        let parser = AnnotationParser::new();
2161        let source = "# @depyler: architecture = \"x64\"";
2162        let a = parser.parse_annotations(source).unwrap();
2163        let la = a.lambda_annotations.unwrap();
2164        assert_eq!(la.architecture, Architecture::X86_64);
2165    }
2166
2167    #[test]
2168    fn test_lambda_architecture_aarch64_alias() {
2169        let parser = AnnotationParser::new();
2170        let source = "# @depyler: architecture = \"aarch64\"";
2171        let a = parser.parse_annotations(source).unwrap();
2172        let la = a.lambda_annotations.unwrap();
2173        assert_eq!(la.architecture, Architecture::Arm64);
2174    }
2175
2176    #[test]
2177    fn test_lambda_architecture_invalid() {
2178        let parser = AnnotationParser::new();
2179        let source = "# @depyler: architecture = \"mips\"";
2180        let result = parser.parse_annotations(source);
2181        assert!(matches!(result, Err(AnnotationError::InvalidValue { .. })));
2182    }
2183
2184    #[test]
2185    fn test_lambda_memory_size_invalid() {
2186        let parser = AnnotationParser::new();
2187        let source = "# @depyler: memory_size = \"lots\"";
2188        let result = parser.parse_annotations(source);
2189        assert!(matches!(result, Err(AnnotationError::InvalidValue { .. })));
2190    }
2191
2192    #[test]
2193    fn test_lambda_timeout_invalid() {
2194        let parser = AnnotationParser::new();
2195        let source = "# @depyler: timeout = \"forever\"";
2196        let result = parser.parse_annotations(source);
2197        assert!(matches!(result, Err(AnnotationError::InvalidValue { .. })));
2198    }
2199
2200    #[test]
2201    fn test_lambda_tracing_true() {
2202        let parser = AnnotationParser::new();
2203        let source = "# @depyler: tracing = \"true\"";
2204        let a = parser.parse_annotations(source).unwrap();
2205        let la = a.lambda_annotations.unwrap();
2206        assert!(la.tracing_enabled);
2207    }
2208
2209    #[test]
2210    fn test_lambda_tracing_false() {
2211        let parser = AnnotationParser::new();
2212        let source = "# @depyler: tracing = \"false\"";
2213        let a = parser.parse_annotations(source).unwrap();
2214        let la = a.lambda_annotations.unwrap();
2215        assert!(!la.tracing_enabled);
2216    }
2217
2218    #[test]
2219    fn test_lambda_cold_start_optimize_false() {
2220        let parser = AnnotationParser::new();
2221        let source = "# @depyler: cold_start_optimize = \"false\"";
2222        let a = parser.parse_annotations(source).unwrap();
2223        let la = a.lambda_annotations.unwrap();
2224        assert!(!la.cold_start_optimize);
2225    }
2226
2227    #[test]
2228    fn test_lambda_event_type_s3() {
2229        let parser = AnnotationParser::new();
2230        let source = "# @depyler: event_type = \"S3Event\"";
2231        let a = parser.parse_annotations(source).unwrap();
2232        let la = a.lambda_annotations.unwrap();
2233        assert_eq!(la.event_type, Some(LambdaEventType::S3Event));
2234    }
2235
2236    #[test]
2237    fn test_lambda_event_type_sns() {
2238        let parser = AnnotationParser::new();
2239        let source = "# @depyler: event_type = \"SnsEvent\"";
2240        let a = parser.parse_annotations(source).unwrap();
2241        let la = a.lambda_annotations.unwrap();
2242        assert_eq!(la.event_type, Some(LambdaEventType::SnsEvent));
2243    }
2244
2245    #[test]
2246    fn test_lambda_event_type_dynamodb() {
2247        let parser = AnnotationParser::new();
2248        let source = "# @depyler: event_type = \"DynamodbEvent\"";
2249        let a = parser.parse_annotations(source).unwrap();
2250        let la = a.lambda_annotations.unwrap();
2251        assert_eq!(la.event_type, Some(LambdaEventType::DynamodbEvent));
2252    }
2253
2254    #[test]
2255    fn test_lambda_event_type_cloudwatch() {
2256        let parser = AnnotationParser::new();
2257        let source = "# @depyler: event_type = \"CloudwatchEvent\"";
2258        let a = parser.parse_annotations(source).unwrap();
2259        let la = a.lambda_annotations.unwrap();
2260        assert_eq!(la.event_type, Some(LambdaEventType::CloudwatchEvent));
2261    }
2262
2263    #[test]
2264    fn test_lambda_event_type_kinesis() {
2265        let parser = AnnotationParser::new();
2266        let source = "# @depyler: event_type = \"KinesisEvent\"";
2267        let a = parser.parse_annotations(source).unwrap();
2268        let la = a.lambda_annotations.unwrap();
2269        assert_eq!(la.event_type, Some(LambdaEventType::KinesisEvent));
2270    }
2271
2272    #[test]
2273    fn test_lambda_event_type_api_gateway_v2() {
2274        let parser = AnnotationParser::new();
2275        let source = "# @depyler: event_type = \"APIGatewayV2HttpRequest\"";
2276        let a = parser.parse_annotations(source).unwrap();
2277        let la = a.lambda_annotations.unwrap();
2278        assert_eq!(
2279            la.event_type,
2280            Some(LambdaEventType::ApiGatewayV2HttpRequest)
2281        );
2282    }
2283
2284    #[test]
2285    fn test_lambda_event_type_custom() {
2286        let parser = AnnotationParser::new();
2287        let source = "# @depyler: event_type = \"MyCustomEvent\"";
2288        let a = parser.parse_annotations(source).unwrap();
2289        let la = a.lambda_annotations.unwrap();
2290        assert_eq!(
2291            la.event_type,
2292            Some(LambdaEventType::Custom("MyCustomEvent".to_string()))
2293        );
2294    }
2295
2296    // ===================================================================
2297    // Custom Attributes Tests
2298    // ===================================================================
2299
2300    #[test]
2301    fn test_custom_custom_attribute_single() {
2302        let parser = AnnotationParser::new();
2303        let source = r#"
2304# @depyler: custom_attribute = "inline"
2305def my_function():
2306    pass
2307        "#;
2308
2309        let annotations = parser.parse_annotations(source).unwrap();
2310        assert_eq!(annotations.custom_attributes.len(), 1);
2311        assert_eq!(annotations.custom_attributes[0], "inline");
2312    }
2313
2314    #[test]
2315    fn test_custom_custom_attribute_multiple() {
2316        let parser = AnnotationParser::new();
2317        let source = r#"
2318# @depyler: custom_attribute = "inline"
2319# @depyler: custom_attribute = "must_use"
2320# @depyler: custom_attribute = "cold"
2321def my_function():
2322    pass
2323        "#;
2324
2325        let annotations = parser.parse_annotations(source).unwrap();
2326        assert_eq!(annotations.custom_attributes.len(), 3);
2327        assert_eq!(annotations.custom_attributes[0], "inline");
2328        assert_eq!(annotations.custom_attributes[1], "must_use");
2329        assert_eq!(annotations.custom_attributes[2], "cold");
2330    }
2331
2332    #[test]
2333    fn test_custom_custom_attribute_with_other_annotations() {
2334        let parser = AnnotationParser::new();
2335        let source = r#"
2336# @depyler: optimization_level = "aggressive"
2337# @depyler: custom_attribute = "inline(always)"
2338# @depyler: performance_critical = "true"
2339def hot_function():
2340    pass
2341        "#;
2342
2343        let annotations = parser.parse_annotations(source).unwrap();
2344        assert_eq!(
2345            annotations.optimization_level,
2346            OptimizationLevel::Aggressive
2347        );
2348        assert_eq!(annotations.custom_attributes.len(), 1);
2349        assert_eq!(annotations.custom_attributes[0], "inline(always)");
2350        assert!(annotations
2351            .performance_hints
2352            .contains(&PerformanceHint::PerformanceCritical));
2353    }
2354
2355    #[test]
2356    fn test_custom_custom_attribute_empty() {
2357        let parser = AnnotationParser::new();
2358        let source = r#"
2359def my_function():
2360    pass
2361        "#;
2362
2363        let annotations = parser.parse_annotations(source).unwrap();
2364        assert_eq!(annotations.custom_attributes.len(), 0);
2365    }
2366
2367    // ===================================================================
2368    // AnnotationValidator Tests
2369    // ===================================================================
2370
2371    #[test]
2372    fn test_validator_new() {
2373        let v = AnnotationValidator::new();
2374        let a = TranspilationAnnotations::default();
2375        assert!(v.validate(&a).is_ok());
2376    }
2377
2378    #[test]
2379    fn test_validator_zero_copy_string_with_owned_conflict() {
2380        let v = AnnotationValidator::new();
2381        let a = TranspilationAnnotations {
2382            string_strategy: StringStrategy::ZeroCopy,
2383            ownership_model: OwnershipModel::Owned,
2384            ..Default::default()
2385        };
2386        let result = v.validate(&a);
2387        assert!(result.is_err());
2388        let errors = result.unwrap_err();
2389        assert!(errors
2390            .iter()
2391            .any(|e| e.contains("Zero-copy string strategy")));
2392    }
2393
2394    #[test]
2395    fn test_validator_refcell_with_thread_safety_conflict() {
2396        let v = AnnotationValidator::new();
2397        let a = TranspilationAnnotations {
2398            thread_safety: ThreadSafety::Required,
2399            interior_mutability: InteriorMutability::RefCell,
2400            ..Default::default()
2401        };
2402        let result = v.validate(&a);
2403        assert!(result.is_err());
2404        let errors = result.unwrap_err();
2405        assert!(errors.iter().any(|e| e.contains("RefCell is not thread-safe")));
2406    }
2407
2408    #[test]
2409    fn test_validator_conflicting_panic_and_error_strategy() {
2410        let v = AnnotationValidator::new();
2411        let a = TranspilationAnnotations {
2412            panic_behavior: PanicBehavior::ReturnError,
2413            error_strategy: ErrorStrategy::Panic,
2414            ..Default::default()
2415        };
2416        let result = v.validate(&a);
2417        assert!(result.is_err());
2418        let errors = result.unwrap_err();
2419        assert!(errors
2420            .iter()
2421            .any(|e| e.contains("Conflicting panic behavior")));
2422    }
2423
2424    #[test]
2425    fn test_validator_aggressive_opt_with_explicit_bounds_conflict() {
2426        let v = AnnotationValidator::new();
2427        let a = TranspilationAnnotations {
2428            optimization_level: OptimizationLevel::Aggressive,
2429            bounds_checking: BoundsChecking::Explicit,
2430            ..Default::default()
2431        };
2432        let result = v.validate(&a);
2433        assert!(result.is_err());
2434        let errors = result.unwrap_err();
2435        assert!(errors
2436            .iter()
2437            .any(|e| e.contains("Aggressive optimization")));
2438    }
2439
2440    #[test]
2441    fn test_validator_multiple_conflicts() {
2442        let v = AnnotationValidator::new();
2443        let a = TranspilationAnnotations {
2444            string_strategy: StringStrategy::ZeroCopy,
2445            ownership_model: OwnershipModel::Owned,
2446            thread_safety: ThreadSafety::Required,
2447            interior_mutability: InteriorMutability::RefCell,
2448            ..Default::default()
2449        };
2450        let result = v.validate(&a);
2451        assert!(result.is_err());
2452        let errors = result.unwrap_err();
2453        assert!(errors.len() >= 2);
2454    }
2455
2456    #[test]
2457    fn test_validator_no_conflict_with_valid_combination() {
2458        let v = AnnotationValidator::new();
2459        let a = TranspilationAnnotations {
2460            string_strategy: StringStrategy::AlwaysOwned,
2461            ownership_model: OwnershipModel::Owned,
2462            thread_safety: ThreadSafety::Required,
2463            interior_mutability: InteriorMutability::ArcMutex,
2464            ..Default::default()
2465        };
2466        assert!(v.validate(&a).is_ok());
2467    }
2468
2469    // ===================================================================
2470    // Suggest Improvements Tests
2471    // ===================================================================
2472
2473    #[test]
2474    fn test_suggest_improvements_perf_critical_not_aggressive() {
2475        let v = AnnotationValidator::new();
2476        let a = TranspilationAnnotations {
2477            performance_hints: vec![PerformanceHint::PerformanceCritical],
2478            optimization_level: OptimizationLevel::Standard,
2479            ..Default::default()
2480        };
2481        let suggestions = v.suggest_improvements(&a);
2482        assert!(suggestions.iter().any(|s| s.contains("aggressive")));
2483    }
2484
2485    #[test]
2486    fn test_suggest_improvements_thread_safe_not_shared() {
2487        let v = AnnotationValidator::new();
2488        let a = TranspilationAnnotations {
2489            thread_safety: ThreadSafety::Required,
2490            ownership_model: OwnershipModel::Owned,
2491            ..Default::default()
2492        };
2493        let suggestions = v.suggest_improvements(&a);
2494        assert!(suggestions.iter().any(|s| s.contains("shared")));
2495    }
2496
2497    #[test]
2498    fn test_suggest_improvements_web_api_no_latency() {
2499        let v = AnnotationValidator::new();
2500        let a = TranspilationAnnotations {
2501            service_type: Some(ServiceType::WebApi),
2502            ..Default::default()
2503        };
2504        let suggestions = v.suggest_improvements(&a);
2505        assert!(suggestions.iter().any(|s| s.contains("latency")));
2506    }
2507
2508    #[test]
2509    fn test_suggest_improvements_none_when_optimal() {
2510        let v = AnnotationValidator::new();
2511        let a = TranspilationAnnotations::default();
2512        let suggestions = v.suggest_improvements(&a);
2513        assert!(suggestions.is_empty());
2514    }
2515
2516    #[test]
2517    fn test_suggest_improvements_web_api_with_latency_no_suggestion() {
2518        let v = AnnotationValidator::new();
2519        let a = TranspilationAnnotations {
2520            service_type: Some(ServiceType::WebApi),
2521            performance_hints: vec![PerformanceHint::OptimizeForLatency],
2522            ..Default::default()
2523        };
2524        let suggestions = v.suggest_improvements(&a);
2525        assert!(!suggestions.iter().any(|s| s.contains("latency")));
2526    }
2527
2528    // ===================================================================
2529    // AnnotationExtractor Tests
2530    // ===================================================================
2531
2532    #[test]
2533    fn test_extractor_new() {
2534        let e = AnnotationExtractor::new();
2535        let result = e.extract_function_annotations("def foo():\n    pass", "bar");
2536        assert!(result.is_none());
2537    }
2538
2539    #[test]
2540    fn test_extractor_function_with_annotation() {
2541        let e = AnnotationExtractor::new();
2542        let source = "# @depyler: ownership = \"borrowed\"\ndef my_func(x):\n    return x";
2543        let result = e.extract_function_annotations(source, "my_func");
2544        assert!(result.is_some());
2545        assert!(result.unwrap().contains("@depyler:"));
2546    }
2547
2548    #[test]
2549    fn test_extractor_function_no_annotation() {
2550        let e = AnnotationExtractor::new();
2551        let source = "# just a regular comment\ndef my_func(x):\n    return x";
2552        let result = e.extract_function_annotations(source, "my_func");
2553        assert!(result.is_none());
2554    }
2555
2556    #[test]
2557    fn test_extractor_function_not_found() {
2558        let e = AnnotationExtractor::new();
2559        let source = "# @depyler: ownership = \"borrowed\"\ndef foo():\n    pass";
2560        let result = e.extract_function_annotations(source, "bar");
2561        assert!(result.is_none());
2562    }
2563
2564    #[test]
2565    fn test_extractor_class_with_annotation() {
2566        let e = AnnotationExtractor::new();
2567        let source = "# @depyler: service_type = \"web_api\"\nclass MyService:\n    pass";
2568        let result = e.extract_class_annotations(source, "MyService");
2569        assert!(result.is_some());
2570        assert!(result.unwrap().contains("@depyler:"));
2571    }
2572
2573    #[test]
2574    fn test_extractor_class_no_annotation() {
2575        let e = AnnotationExtractor::new();
2576        let source = "# regular comment\nclass MyClass:\n    pass";
2577        let result = e.extract_class_annotations(source, "MyClass");
2578        assert!(result.is_none());
2579    }
2580
2581    #[test]
2582    fn test_extractor_class_not_found() {
2583        let e = AnnotationExtractor::new();
2584        let source = "# @depyler: ownership = \"borrowed\"\nclass Foo:\n    pass";
2585        let result = e.extract_class_annotations(source, "Bar");
2586        assert!(result.is_none());
2587    }
2588
2589    #[test]
2590    fn test_extractor_class_with_parentheses() {
2591        let e = AnnotationExtractor::new();
2592        let source = "# @depyler: ownership = \"shared\"\nclass Child(Parent):\n    pass";
2593        let result = e.extract_class_annotations(source, "Child");
2594        assert!(result.is_some());
2595    }
2596
2597    // ===================================================================
2598    // Serialization Tests
2599    // ===================================================================
2600
2601    #[test]
2602    fn test_serialize_transpilation_annotations() {
2603        let a = TranspilationAnnotations::default();
2604        let json = serde_json::to_string(&a).unwrap();
2605        assert!(json.contains("Conservative"));
2606        assert!(json.contains("Owned"));
2607    }
2608
2609    #[test]
2610    fn test_deserialize_transpilation_annotations() {
2611        let a = TranspilationAnnotations::default();
2612        let json = serde_json::to_string(&a).unwrap();
2613        let deserialized: TranspilationAnnotations = serde_json::from_str(&json).unwrap();
2614        assert_eq!(a, deserialized);
2615    }
2616
2617    #[test]
2618    fn test_serialize_lambda_annotations() {
2619        let la = LambdaAnnotations::default();
2620        let json = serde_json::to_string(&la).unwrap();
2621        assert!(json.contains("ProvidedAl2"));
2622        assert!(json.contains("Arm64"));
2623    }
2624
2625    #[test]
2626    fn test_deserialize_lambda_annotations() {
2627        let la = LambdaAnnotations::default();
2628        let json = serde_json::to_string(&la).unwrap();
2629        let deserialized: LambdaAnnotations = serde_json::from_str(&json).unwrap();
2630        assert_eq!(la, deserialized);
2631    }
2632
2633    #[test]
2634    fn test_serialize_roundtrip_all_event_types() {
2635        let event_types = vec![
2636            LambdaEventType::Auto,
2637            LambdaEventType::S3Event,
2638            LambdaEventType::ApiGatewayProxyRequest,
2639            LambdaEventType::ApiGatewayV2HttpRequest,
2640            LambdaEventType::SqsEvent,
2641            LambdaEventType::SnsEvent,
2642            LambdaEventType::DynamodbEvent,
2643            LambdaEventType::EventBridgeEvent(None),
2644            LambdaEventType::EventBridgeEvent(Some("Order".to_string())),
2645            LambdaEventType::CloudwatchEvent,
2646            LambdaEventType::KinesisEvent,
2647            LambdaEventType::Custom("MyEvent".to_string()),
2648        ];
2649        for et in event_types {
2650            let json = serde_json::to_string(&et).unwrap();
2651            let deserialized: LambdaEventType = serde_json::from_str(&json).unwrap();
2652            assert_eq!(et, deserialized);
2653        }
2654    }
2655
2656    #[test]
2657    fn test_serialize_roundtrip_with_lambda_annotations() {
2658        let la = LambdaAnnotations {
2659            event_type: Some(LambdaEventType::SqsEvent),
2660            memory_size: 512,
2661            timeout: Some(60),
2662            tracing_enabled: true,
2663            batch_failure_reporting: true,
2664            ..Default::default()
2665        };
2666        let a = TranspilationAnnotations {
2667            lambda_annotations: Some(la),
2668            service_type: Some(ServiceType::WebApi),
2669            pattern: Some("microservice".to_string()),
2670            ..Default::default()
2671        };
2672
2673        let json = serde_json::to_string(&a).unwrap();
2674        let deserialized: TranspilationAnnotations = serde_json::from_str(&json).unwrap();
2675        assert_eq!(a, deserialized);
2676    }
2677
2678    // ===================================================================
2679    // Clone and Debug Trait Tests
2680    // ===================================================================
2681
2682    #[test]
2683    fn test_transpilation_annotations_clone() {
2684        let a = TranspilationAnnotations {
2685            type_strategy: TypeStrategy::Aggressive,
2686            invariants: vec!["x > 0".to_string()],
2687            ..Default::default()
2688        };
2689        let b = a.clone();
2690        assert_eq!(a, b);
2691    }
2692
2693    #[test]
2694    fn test_lambda_annotations_clone() {
2695        let la = LambdaAnnotations {
2696            memory_size: 1024,
2697            event_type: Some(LambdaEventType::S3Event),
2698            ..Default::default()
2699        };
2700        let cloned = la.clone();
2701        assert_eq!(la, cloned);
2702    }
2703
2704    #[test]
2705    fn test_annotation_extractor_clone() {
2706        let e = AnnotationExtractor::new();
2707        let _cloned = e.clone();
2708        // If this compiles and runs, Clone works
2709    }
2710
2711    #[test]
2712    fn test_annotation_parser_new_and_default_equivalent() {
2713        let p1 = AnnotationParser::new();
2714        let p2 = AnnotationParser::default();
2715        // Both should produce identical results on the same input
2716        let source = "# @depyler: ownership = \"shared\"";
2717        let a1 = p1.parse_annotations(source).unwrap();
2718        let a2 = p2.parse_annotations(source).unwrap();
2719        assert_eq!(a1, a2);
2720    }
2721
2722    #[test]
2723    fn test_annotation_validator_debug() {
2724        let v = AnnotationValidator::new();
2725        let debug_str = format!("{v:?}");
2726        assert!(debug_str.contains("AnnotationValidator"));
2727    }
2728
2729    #[test]
2730    fn test_annotation_extractor_debug() {
2731        let e = AnnotationExtractor::new();
2732        let debug_str = format!("{e:?}");
2733        assert!(debug_str.contains("AnnotationExtractor"));
2734    }
2735
2736    // ===================================================================
2737    // Enum Variant Equality and Hash Tests
2738    // ===================================================================
2739
2740    #[test]
2741    fn test_lambda_event_type_hash_in_collections() {
2742        use std::collections::HashSet;
2743        let mut set = HashSet::new();
2744        set.insert(LambdaEventType::Auto);
2745        set.insert(LambdaEventType::S3Event);
2746        set.insert(LambdaEventType::Auto); // duplicate
2747        assert_eq!(set.len(), 2);
2748    }
2749
2750    #[test]
2751    fn test_enum_equality() {
2752        assert_eq!(TypeStrategy::Conservative, TypeStrategy::Conservative);
2753        assert_ne!(TypeStrategy::Conservative, TypeStrategy::Aggressive);
2754        assert_eq!(OwnershipModel::Owned, OwnershipModel::Owned);
2755        assert_ne!(OwnershipModel::Owned, OwnershipModel::Borrowed);
2756        assert_eq!(
2757            Termination::BoundedLoop(10),
2758            Termination::BoundedLoop(10)
2759        );
2760        assert_ne!(Termination::BoundedLoop(10), Termination::BoundedLoop(20));
2761    }
2762
2763    // ===================================================================
2764    // Parser Edge Cases
2765    // ===================================================================
2766
2767    #[test]
2768    fn test_parse_annotation_with_extra_whitespace_before_key() {
2769        let parser = AnnotationParser::new();
2770        // Extra spaces between # and @depyler are handled by \s* in the regex
2771        let source = "#   @depyler: ownership = \"shared\"";
2772        let a = parser.parse_annotations(source).unwrap();
2773        assert_eq!(a.ownership_model, OwnershipModel::Shared);
2774    }
2775
2776    #[test]
2777    fn test_parse_annotation_mixed_with_plain_comments() {
2778        let parser = AnnotationParser::new();
2779        let source = r#"
2780# This is a regular comment
2781# @depyler: ownership = "borrowed"
2782# Another plain comment
2783def foo():
2784    pass
2785        "#;
2786        let a = parser.parse_annotations(source).unwrap();
2787        assert_eq!(a.ownership_model, OwnershipModel::Borrowed);
2788    }
2789
2790    #[test]
2791    fn test_parse_all_annotations_combined() {
2792        let parser = AnnotationParser::new();
2793        let source = r#"
2794# @depyler: type_strategy = "aggressive"
2795# @depyler: ownership = "shared"
2796# @depyler: safety_level = "unsafe_allowed"
2797# @depyler: fallback = "manual"
2798# @depyler: bounds_checking = "implicit"
2799# @depyler: optimization_level = "conservative"
2800# @depyler: thread_safety = "required"
2801# @depyler: interior_mutability = "arc_mutex"
2802# @depyler: string_strategy = "always_owned"
2803# @depyler: hash_strategy = "ahash"
2804# @depyler: panic_behavior = "abort"
2805# @depyler: error_strategy = "option_type"
2806# @depyler: global_strategy = "once_cell"
2807# @depyler: termination = "bounded_50"
2808# @depyler: verify_bounds = "true"
2809# @depyler: service_type = "cli"
2810# @depyler: migration_strategy = "hybrid"
2811# @depyler: compatibility_layer = "ctypes"
2812# @depyler: pattern = "singleton"
2813def full_function():
2814    pass
2815        "#;
2816
2817        let a = parser.parse_annotations(source).unwrap();
2818        assert_eq!(a.type_strategy, TypeStrategy::Aggressive);
2819        assert_eq!(a.ownership_model, OwnershipModel::Shared);
2820        assert_eq!(a.safety_level, SafetyLevel::UnsafeAllowed);
2821        assert_eq!(a.fallback_strategy, FallbackStrategy::Manual);
2822        assert_eq!(a.bounds_checking, BoundsChecking::Implicit);
2823        assert_eq!(a.optimization_level, OptimizationLevel::Conservative);
2824        assert_eq!(a.thread_safety, ThreadSafety::Required);
2825        assert_eq!(a.interior_mutability, InteriorMutability::ArcMutex);
2826        assert_eq!(a.string_strategy, StringStrategy::AlwaysOwned);
2827        assert_eq!(a.hash_strategy, HashStrategy::AHash);
2828        assert_eq!(a.panic_behavior, PanicBehavior::Abort);
2829        assert_eq!(a.error_strategy, ErrorStrategy::OptionType);
2830        assert_eq!(a.global_strategy, GlobalStrategy::OnceCell);
2831        assert_eq!(a.termination, Termination::BoundedLoop(50));
2832        assert!(a.verify_bounds);
2833        assert_eq!(a.service_type, Some(ServiceType::Cli));
2834        assert_eq!(a.migration_strategy, Some(MigrationStrategy::Hybrid));
2835        assert_eq!(a.compatibility_layer, Some(CompatibilityLayer::CTypes));
2836        assert_eq!(a.pattern, Some("singleton".to_string()));
2837    }
2838
2839    #[test]
2840    fn test_parse_only_comments_no_depyler_prefix() {
2841        let parser = AnnotationParser::new();
2842        let source = "# just a comment\n# another one\n";
2843        let a = parser.parse_annotations(source).unwrap();
2844        assert_eq!(a, TranspilationAnnotations::default());
2845    }
2846
2847    #[test]
2848    fn test_extractor_function_at_first_line() {
2849        let e = AnnotationExtractor::new();
2850        let source = "def first_func():\n    pass";
2851        let result = e.extract_function_annotations(source, "first_func");
2852        assert!(result.is_none());
2853    }
2854
2855    #[test]
2856    fn test_extractor_empty_source() {
2857        let e = AnnotationExtractor::new();
2858        let result = e.extract_function_annotations("", "anything");
2859        assert!(result.is_none());
2860    }
2861
2862    #[test]
2863    fn test_extractor_class_empty_source() {
2864        let e = AnnotationExtractor::new();
2865        let result = e.extract_class_annotations("", "anything");
2866        assert!(result.is_none());
2867    }
2868
2869    // ========================================================================
2870    // S9B7: Coverage tests for annotations
2871    // ========================================================================
2872
2873    #[test]
2874    fn test_s9b7_annotation_error_display_invalid_syntax() {
2875        let err = AnnotationError::InvalidSyntax("bad format".to_string());
2876        assert_eq!(err.to_string(), "Invalid annotation syntax: bad format");
2877    }
2878
2879    #[test]
2880    fn test_s9b7_annotation_error_display_unknown_key() {
2881        let err = AnnotationError::UnknownKey("foobar".to_string());
2882        assert_eq!(err.to_string(), "Unknown annotation key: foobar");
2883    }
2884
2885    #[test]
2886    fn test_s9b7_annotation_error_display_invalid_value() {
2887        let err = AnnotationError::InvalidValue {
2888            key: "type_strategy".to_string(),
2889            value: "bad_val".to_string(),
2890        };
2891        let msg = err.to_string();
2892        assert!(msg.contains("type_strategy"));
2893        assert!(msg.contains("bad_val"));
2894    }
2895
2896    #[test]
2897    fn test_s9b7_annotation_error_debug() {
2898        let err = AnnotationError::UnknownKey("x".to_string());
2899        let debug = format!("{err:?}");
2900        assert!(debug.contains("UnknownKey"));
2901    }
2902
2903    #[test]
2904    fn test_s9b7_validator_no_conflicts_default() {
2905        let validator = AnnotationValidator::new();
2906        let annotations = TranspilationAnnotations::default();
2907        assert!(validator.validate(&annotations).is_ok());
2908    }
2909
2910    #[test]
2911    fn test_s9b7_validator_thread_safety_refcell_conflict() {
2912        let validator = AnnotationValidator::new();
2913        let annotations = TranspilationAnnotations {
2914            thread_safety: ThreadSafety::Required,
2915            interior_mutability: InteriorMutability::RefCell,
2916            ..Default::default()
2917        };
2918        let result = validator.validate(&annotations);
2919        assert!(result.is_err());
2920        let errors = result.unwrap_err();
2921        assert!(errors.iter().any(|e| e.contains("RefCell")));
2922    }
2923
2924    #[test]
2925    fn test_s9b7_validator_panic_error_conflict() {
2926        let validator = AnnotationValidator::new();
2927        let annotations = TranspilationAnnotations {
2928            panic_behavior: PanicBehavior::ReturnError,
2929            error_strategy: ErrorStrategy::Panic,
2930            ..Default::default()
2931        };
2932        let result = validator.validate(&annotations);
2933        assert!(result.is_err());
2934        let errors = result.unwrap_err();
2935        assert!(errors.iter().any(|e| e.contains("Conflicting panic")));
2936    }
2937
2938    #[test]
2939    fn test_s9b7_validator_aggressive_opt_bounds_conflict() {
2940        let validator = AnnotationValidator::new();
2941        let annotations = TranspilationAnnotations {
2942            optimization_level: OptimizationLevel::Aggressive,
2943            bounds_checking: BoundsChecking::Explicit,
2944            ..Default::default()
2945        };
2946        let result = validator.validate(&annotations);
2947        assert!(result.is_err());
2948        let errors = result.unwrap_err();
2949        assert!(errors.iter().any(|e| e.contains("bounds checking")));
2950    }
2951
2952    #[test]
2953    fn test_s9b7_suggest_improvements_performance_critical() {
2954        let validator = AnnotationValidator::new();
2955        let mut annotations = TranspilationAnnotations::default();
2956        annotations
2957            .performance_hints
2958            .push(PerformanceHint::PerformanceCritical);
2959        let suggestions = validator.suggest_improvements(&annotations);
2960        assert!(suggestions.iter().any(|s| s.contains("aggressive")));
2961    }
2962
2963    #[test]
2964    fn test_s9b7_suggest_improvements_thread_safety_shared() {
2965        let validator = AnnotationValidator::new();
2966        let annotations = TranspilationAnnotations {
2967            thread_safety: ThreadSafety::Required,
2968            ownership_model: OwnershipModel::Owned,
2969            ..Default::default()
2970        };
2971        let suggestions = validator.suggest_improvements(&annotations);
2972        assert!(suggestions.iter().any(|s| s.contains("shared")));
2973    }
2974
2975    #[test]
2976    fn test_s9b7_suggest_improvements_web_api_latency() {
2977        let validator = AnnotationValidator::new();
2978        let annotations = TranspilationAnnotations {
2979            service_type: Some(ServiceType::WebApi),
2980            ..Default::default()
2981        };
2982        let suggestions = validator.suggest_improvements(&annotations);
2983        assert!(suggestions.iter().any(|s| s.contains("latency")));
2984    }
2985
2986    #[test]
2987    fn test_s9b7_suggest_improvements_no_suggestions() {
2988        let validator = AnnotationValidator::new();
2989        let annotations = TranspilationAnnotations::default();
2990        let suggestions = validator.suggest_improvements(&annotations);
2991        assert!(suggestions.is_empty());
2992    }
2993
2994    #[test]
2995    fn test_s9b7_lambda_annotations_default() {
2996        let la = LambdaAnnotations::default();
2997        assert!(matches!(la.runtime, LambdaRuntime::ProvidedAl2));
2998        assert!(la.event_type.is_none());
2999        assert!(la.cold_start_optimize);
3000        assert_eq!(la.memory_size, 128);
3001        assert!(matches!(la.architecture, Architecture::Arm64));
3002        assert!(!la.custom_serialization);
3003        assert!(!la.batch_failure_reporting);
3004        assert!(la.timeout.is_none());
3005        assert!(!la.tracing_enabled);
3006        assert!(la.environment_variables.is_empty());
3007    }
3008
3009    #[test]
3010    fn test_s9b7_parse_termination_bounded_loop() {
3011        let parser = AnnotationParser::new();
3012        let source = "# @depyler: termination = bounded_100\n";
3013        let annotations = parser.parse_annotations(source).unwrap();
3014        assert_eq!(annotations.termination, Termination::BoundedLoop(100));
3015    }
3016
3017    #[test]
3018    fn test_s9b7_parse_termination_invalid() {
3019        let parser = AnnotationParser::new();
3020        let source = "# @depyler: termination = bounded_abc\n";
3021        let result = parser.parse_annotations(source);
3022        assert!(result.is_err());
3023    }
3024
3025    #[test]
3026    fn test_s9b7_parse_invariant() {
3027        let parser = AnnotationParser::new();
3028        let source = "# @depyler: invariant = x_greater_zero\n";
3029        let annotations = parser.parse_annotations(source).unwrap();
3030        assert!(annotations.invariants.contains(&"x_greater_zero".to_string()));
3031    }
3032
3033    #[test]
3034    fn test_s9b7_parse_verify_bounds_true() {
3035        let parser = AnnotationParser::new();
3036        let source = "# @depyler: verify_bounds = true\n";
3037        let annotations = parser.parse_annotations(source).unwrap();
3038        assert!(annotations.verify_bounds);
3039    }
3040
3041    #[test]
3042    fn test_s9b7_parse_verify_bounds_false() {
3043        let parser = AnnotationParser::new();
3044        let source = "# @depyler: verify_bounds = false\n";
3045        let annotations = parser.parse_annotations(source).unwrap();
3046        assert!(!annotations.verify_bounds);
3047    }
3048
3049    #[test]
3050    fn test_s9b7_parse_pattern() {
3051        let parser = AnnotationParser::new();
3052        let source = "# @depyler: pattern = singleton\n";
3053        let annotations = parser.parse_annotations(source).unwrap();
3054        assert_eq!(annotations.pattern, Some("singleton".to_string()));
3055    }
3056
3057    #[test]
3058    fn test_s9b7_parse_custom_attribute() {
3059        let parser = AnnotationParser::new();
3060        let source = "# @depyler: custom_attribute = my_attr\n# @depyler: custom_attribute = another\n";
3061        let annotations = parser.parse_annotations(source).unwrap();
3062        assert_eq!(annotations.custom_attributes.len(), 2);
3063        assert!(annotations.custom_attributes.contains(&"my_attr".to_string()));
3064        assert!(annotations.custom_attributes.contains(&"another".to_string()));
3065    }
3066
3067    #[test]
3068    fn test_s9b7_parse_global_strategy_lazy_static() {
3069        let parser = AnnotationParser::new();
3070        let source = "# @depyler: global_strategy = lazy_static\n";
3071        let annotations = parser.parse_annotations(source).unwrap();
3072        assert_eq!(annotations.global_strategy, GlobalStrategy::LazyStatic);
3073    }
3074
3075    #[test]
3076    fn test_s9b7_parse_global_strategy_once_cell() {
3077        let parser = AnnotationParser::new();
3078        let source = "# @depyler: global_strategy = once_cell\n";
3079        let annotations = parser.parse_annotations(source).unwrap();
3080        assert_eq!(annotations.global_strategy, GlobalStrategy::OnceCell);
3081    }
3082
3083    #[test]
3084    fn test_s9b7_parse_function_annotations_delegates() {
3085        let parser = AnnotationParser::new();
3086        let source = "# @depyler: ownership = borrowed\n";
3087        let annotations = parser.parse_function_annotations(source).unwrap();
3088        assert_eq!(annotations.ownership_model, OwnershipModel::Borrowed);
3089    }
3090
3091    #[test]
3092    fn test_s9b7_extractor_no_annotation_above_function() {
3093        let e = AnnotationExtractor::new();
3094        let source = "# just a comment\ndef my_func():\n    pass";
3095        let result = e.extract_function_annotations(source, "my_func");
3096        assert!(result.is_none());
3097    }
3098
3099    #[test]
3100    fn test_s9b7_extractor_no_matching_function() {
3101        let e = AnnotationExtractor::new();
3102        let source = "# @depyler: ownership = owned\ndef other():\n    pass";
3103        let result = e.extract_function_annotations(source, "nonexistent");
3104        assert!(result.is_none());
3105    }
3106
3107    #[test]
3108    fn test_s9b7_extractor_class_no_annotation() {
3109        let e = AnnotationExtractor::new();
3110        let source = "# just a comment\nclass MyClass:\n    pass";
3111        let result = e.extract_class_annotations(source, "MyClass");
3112        assert!(result.is_none());
3113    }
3114
3115    #[test]
3116    fn test_s9b7_extractor_class_no_match() {
3117        let e = AnnotationExtractor::new();
3118        let source = "# @depyler: ownership = shared\nclass Other:\n    pass";
3119        let result = e.extract_class_annotations(source, "NotHere");
3120        assert!(result.is_none());
3121    }
3122
3123    #[test]
3124    fn test_s9b7_annotation_validator_default() {
3125        let v = AnnotationValidator;
3126        let debug = format!("{:?}", v);
3127        assert!(debug.contains("AnnotationValidator"));
3128    }
3129
3130    #[test]
3131    fn test_s9b7_lambda_event_type_hash() {
3132        use std::collections::HashSet;
3133        let mut set = HashSet::new();
3134        set.insert(LambdaEventType::Auto);
3135        set.insert(LambdaEventType::S3Event);
3136        set.insert(LambdaEventType::SqsEvent);
3137        assert_eq!(set.len(), 3);
3138    }
3139
3140    // ========================================================================
3141    // DEPYLER-99MODE-S11: Coverage tests for untested annotation paths
3142    // ========================================================================
3143
3144    #[test]
3145    fn test_s11_parse_optimization_hint_async_ready() {
3146        let parser = AnnotationParser::new();
3147        let source = "# @depyler: optimization_hint = \"async_ready\"";
3148        let result = parser.parse_annotations(source);
3149        // async_ready is experimental - it prints a warning but does NOT error
3150        assert!(result.is_ok());
3151        // No performance hints should be added (async_ready just warns)
3152        let annotations = result.unwrap();
3153        assert!(!annotations
3154            .performance_hints
3155            .contains(&PerformanceHint::Vectorize));
3156    }
3157
3158    #[test]
3159    fn test_s11_parse_optimization_hint_vectorize() {
3160        let parser = AnnotationParser::new();
3161        let source = "# @depyler: optimization_hint = \"vectorize\"";
3162        let result = parser.parse_annotations(source).unwrap();
3163        assert!(result
3164            .performance_hints
3165            .contains(&PerformanceHint::Vectorize));
3166    }
3167
3168    #[test]
3169    fn test_s11_parse_custom_attribute_serde_roundtrip() {
3170        let parser = AnnotationParser::new();
3171        let source = "# @depyler: custom_attribute = \"#[derive(Clone)]\"";
3172        let result = parser.parse_annotations(source).unwrap();
3173        assert!(result
3174            .custom_attributes
3175            .contains(&"#[derive(Clone)]".to_string()));
3176
3177        let json = serde_json::to_string(&result).unwrap();
3178        let deserialized: TranspilationAnnotations = serde_json::from_str(&json).unwrap();
3179        assert_eq!(result.custom_attributes, deserialized.custom_attributes);
3180    }
3181
3182    #[test]
3183    fn test_s11_parse_invariant_annotation() {
3184        let parser = AnnotationParser::new();
3185        let source = "# @depyler: invariant = \"x > 0\"";
3186        let result = parser.parse_annotations(source).unwrap();
3187        assert_eq!(result.invariants.len(), 1);
3188        assert!(result.invariants.contains(&"x > 0".to_string()));
3189    }
3190
3191    #[test]
3192    fn test_s11_parse_batch_failure_reporting() {
3193        let parser = AnnotationParser::new();
3194        let source = "# @depyler: batch_failure_reporting = \"true\"";
3195        let result = parser.parse_annotations(source).unwrap();
3196        let lambda = result.lambda_annotations.unwrap();
3197        assert!(lambda.batch_failure_reporting);
3198    }
3199
3200    #[test]
3201    fn test_s11_parse_custom_serialization() {
3202        let parser = AnnotationParser::new();
3203        let source = "# @depyler: custom_serialization = \"true\"";
3204        let result = parser.parse_annotations(source).unwrap();
3205        let lambda = result.lambda_annotations.unwrap();
3206        assert!(lambda.custom_serialization);
3207    }
3208
3209    // === Session 12: AnnotationExtractor tests ===
3210
3211    #[test]
3212    fn test_s12_extract_function_annotations_found() {
3213        let extractor = AnnotationExtractor::new();
3214        let source = r#"
3215# @depyler: ownership = "borrowed"
3216def my_func(x: int) -> int:
3217    return x + 1
3218"#;
3219        let result = extractor.extract_function_annotations(source, "my_func");
3220        assert!(result.is_some(), "Expected to find annotations for my_func");
3221        assert!(result.unwrap().contains("@depyler: ownership"));
3222    }
3223
3224    #[test]
3225    fn test_s12_extract_function_annotations_not_found() {
3226        let extractor = AnnotationExtractor::new();
3227        let source = r#"
3228def my_func(x: int) -> int:
3229    return x + 1
3230"#;
3231        let result = extractor.extract_function_annotations(source, "my_func");
3232        assert!(result.is_none());
3233    }
3234
3235    #[test]
3236    fn test_s12_extract_function_annotations_wrong_name() {
3237        let extractor = AnnotationExtractor::new();
3238        let source = r#"
3239# @depyler: ownership = "borrowed"
3240def other_func(x: int) -> int:
3241    return x + 1
3242"#;
3243        let result = extractor.extract_function_annotations(source, "my_func");
3244        assert!(result.is_none());
3245    }
3246
3247    #[test]
3248    fn test_s12_extract_function_annotations_multiple() {
3249        let extractor = AnnotationExtractor::new();
3250        let source = r#"
3251# @depyler: ownership = "borrowed"
3252# @depyler: string_strategy = "zero_copy"
3253def my_func(x: int) -> int:
3254    return x + 1
3255"#;
3256        let result = extractor.extract_function_annotations(source, "my_func");
3257        assert!(result.is_some());
3258        let anno = result.unwrap();
3259        assert!(anno.contains("ownership"));
3260        assert!(anno.contains("string_strategy"));
3261    }
3262
3263    #[test]
3264    fn test_s12_extract_class_annotations_found() {
3265        let extractor = AnnotationExtractor::new();
3266        let source = r#"
3267# @depyler: ownership = "owned"
3268class MyClass:
3269    def __init__(self):
3270        pass
3271"#;
3272        let result = extractor.extract_class_annotations(source, "MyClass");
3273        assert!(result.is_some(), "Expected to find annotations for MyClass");
3274        assert!(result.unwrap().contains("@depyler: ownership"));
3275    }
3276
3277    #[test]
3278    fn test_s12_extract_class_annotations_not_found() {
3279        let extractor = AnnotationExtractor::new();
3280        let source = r#"
3281class MyClass:
3282    pass
3283"#;
3284        let result = extractor.extract_class_annotations(source, "MyClass");
3285        assert!(result.is_none());
3286    }
3287
3288    #[test]
3289    fn test_s12_extract_class_annotations_with_parent() {
3290        let extractor = AnnotationExtractor::new();
3291        let source = r#"
3292# @depyler: ownership = "borrowed"
3293class Child(Parent):
3294    pass
3295"#;
3296        let result = extractor.extract_class_annotations(source, "Child");
3297        assert!(result.is_some());
3298    }
3299
3300    #[test]
3301    fn test_s12_extract_function_at_start_of_file() {
3302        let extractor = AnnotationExtractor::new();
3303        let source = r#"# @depyler: ownership = "borrowed"
3304def first_func():
3305    pass
3306"#;
3307        let result = extractor.extract_function_annotations(source, "first_func");
3308        assert!(result.is_some());
3309    }
3310
3311    #[test]
3312    fn test_s12_extractor_default() {
3313        let extractor = AnnotationExtractor::default();
3314        let source = "def foo():\n    pass\n";
3315        let result = extractor.extract_function_annotations(source, "foo");
3316        assert!(result.is_none());
3317    }
3318
3319    #[test]
3320    fn test_s12_extract_function_among_many() {
3321        let extractor = AnnotationExtractor::new();
3322        let source = r#"
3323def func_a():
3324    pass
3325
3326# @depyler: bounds_checking = "explicit"
3327def func_b():
3328    pass
3329
3330def func_c():
3331    pass
3332"#;
3333        let result = extractor.extract_function_annotations(source, "func_b");
3334        assert!(result.is_some());
3335        assert!(result.unwrap().contains("bounds_checking"));
3336
3337        let result_a = extractor.extract_function_annotations(source, "func_a");
3338        assert!(result_a.is_none());
3339
3340        let result_c = extractor.extract_function_annotations(source, "func_c");
3341        assert!(result_c.is_none());
3342    }
3343
3344    // ===== Session 12 Batch 29: Coverage gap tests =====
3345
3346    #[test]
3347    fn test_s12_extract_class_annotations_multiple() {
3348        let extractor = AnnotationExtractor::new();
3349        let source = r#"# @depyler: ownership = "shared"
3350# @depyler: thread_safety = "required"
3351class MyService:
3352    pass
3353"#;
3354        let result = extractor.extract_class_annotations(source, "MyService");
3355        assert!(result.is_some(), "Expected annotations");
3356        let annotations = result.unwrap();
3357        assert!(annotations.contains("ownership"));
3358        assert!(annotations.contains("thread_safety"));
3359    }
3360
3361    #[test]
3362    fn test_s12_extract_class_annotations_wrong_name() {
3363        let extractor = AnnotationExtractor::new();
3364        let source = r#"# @depyler: ownership = "shared"
3365class MyService:
3366    pass
3367"#;
3368        let result = extractor.extract_class_annotations(source, "OtherService");
3369        assert!(result.is_none());
3370    }
3371
3372    #[test]
3373    fn test_s12_extract_class_annotations_with_base_class() {
3374        let extractor = AnnotationExtractor::new();
3375        let source = r#"# @depyler: thread_safety = "required"
3376class MyService(BaseService):
3377    pass
3378"#;
3379        let result = extractor.extract_class_annotations(source, "MyService");
3380        assert!(result.is_some());
3381    }
3382
3383    #[test]
3384    fn test_s12_suggest_improvements_multiple_triggers() {
3385        let validator = AnnotationValidator::new();
3386        let mut annotations = TranspilationAnnotations::default();
3387        annotations
3388            .performance_hints
3389            .push(PerformanceHint::PerformanceCritical);
3390        annotations.optimization_level = OptimizationLevel::Standard;
3391        annotations.thread_safety = ThreadSafety::Required;
3392        annotations.ownership_model = OwnershipModel::Owned;
3393        annotations.service_type = Some(ServiceType::WebApi);
3394
3395        let suggestions = validator.suggest_improvements(&annotations);
3396        assert!(
3397            suggestions.len() >= 2,
3398            "Expected at least 2 suggestions, got {}",
3399            suggestions.len()
3400        );
3401    }
3402
3403    #[test]
3404    fn test_s12_suggest_improvements_perf_with_aggressive() {
3405        let validator = AnnotationValidator::new();
3406        let mut annotations = TranspilationAnnotations::default();
3407        annotations
3408            .performance_hints
3409            .push(PerformanceHint::PerformanceCritical);
3410        annotations.optimization_level = OptimizationLevel::Aggressive;
3411
3412        let suggestions = validator.suggest_improvements(&annotations);
3413        assert!(
3414            !suggestions
3415                .iter()
3416                .any(|s: &String| s.contains("optimization_level")),
3417            "Should not suggest optimization_level when already aggressive"
3418        );
3419    }
3420
3421    #[test]
3422    fn test_s12_suggest_improvements_thread_with_shared() {
3423        let validator = AnnotationValidator::new();
3424        let annotations = TranspilationAnnotations {
3425            thread_safety: ThreadSafety::Required,
3426            ownership_model: OwnershipModel::Shared,
3427            ..Default::default()
3428        };
3429        let suggestions = validator.suggest_improvements(&annotations);
3430        assert!(
3431            !suggestions
3432                .iter()
3433                .any(|s: &String| s.contains("ownership")),
3434            "Should not suggest ownership when already shared"
3435        );
3436    }
3437
3438    #[test]
3439    fn test_s12_parse_annotations_empty_source() {
3440        let parser = AnnotationParser::new();
3441        let result = parser.parse_annotations("");
3442        assert!(result.is_ok());
3443        let annotations = result.unwrap();
3444        assert_eq!(annotations.optimization_level, OptimizationLevel::Standard);
3445    }
3446
3447    #[test]
3448    fn test_s12_parse_annotations_no_depyler_comments() {
3449        let parser = AnnotationParser::new();
3450        let source = "# This is a regular comment\ndef foo():\n    pass\n";
3451        let result = parser.parse_annotations(source);
3452        assert!(result.is_ok());
3453        let annotations = result.unwrap();
3454        assert_eq!(annotations.optimization_level, OptimizationLevel::Standard);
3455    }
3456
3457    #[test]
3458    fn test_s12_parse_annotations_full() {
3459        let parser = AnnotationParser::new();
3460        let source = r#"# @depyler: optimization_level = "aggressive"
3461# @depyler: ownership = "shared"
3462# @depyler: thread_safety = "required"
3463# @depyler: optimization_hint = "latency"
3464def serve():
3465    pass
3466"#;
3467        let result = parser.parse_annotations(source);
3468        assert!(result.is_ok());
3469        let annotations = result.unwrap();
3470        assert_eq!(annotations.optimization_level, OptimizationLevel::Aggressive);
3471        assert_eq!(annotations.ownership_model, OwnershipModel::Shared);
3472        assert_eq!(annotations.thread_safety, ThreadSafety::Required);
3473    }
3474
3475    #[test]
3476    fn test_s12_parse_annotations_unknown_key() {
3477        let parser = AnnotationParser::new();
3478        let source = "# @depyler: unknown_key = \"value\"\n";
3479        let result = parser.parse_annotations(source);
3480        assert!(result.is_err());
3481    }
3482
3483    #[test]
3484    fn test_s12_parse_annotations_lambda_runtime() {
3485        let parser = AnnotationParser::new();
3486        let source = "# @depyler: lambda_runtime = \"provided.al2\"\n";
3487        let result = parser.parse_annotations(source);
3488        assert!(result.is_ok());
3489        let annotations = result.unwrap();
3490        assert!(annotations.lambda_annotations.is_some());
3491    }
3492
3493    #[test]
3494    fn test_s12_validate_annotations_valid() {
3495        let validator = AnnotationValidator::new();
3496        let annotations = TranspilationAnnotations::default();
3497        let result = validator.validate(&annotations);
3498        assert!(result.is_ok());
3499    }
3500
3501    #[test]
3502    fn test_s12_validate_annotations_unsafe_with_bounds() {
3503        let validator = AnnotationValidator::new();
3504        let annotations = TranspilationAnnotations {
3505            safety_level: SafetyLevel::UnsafeAllowed,
3506            bounds_checking: BoundsChecking::Explicit,
3507            ..Default::default()
3508        };
3509        let _ = validator.validate(&annotations);
3510    }
3511
3512    #[test]
3513    fn test_s12_extract_func_annotations_with_gap() {
3514        let extractor = AnnotationExtractor::new();
3515        let source = r#"# @depyler: optimization_level = "aggressive"
3516
3517def process(data):
3518    return data
3519"#;
3520        let _ = extractor.extract_function_annotations(source, "process");
3521    }
3522
3523    #[test]
3524    fn test_s12_parse_function_annotations() {
3525        let parser = AnnotationParser::new();
3526        let source = r#"# @depyler: optimization_level = "aggressive"
3527def process(data):
3528    return data
3529"#;
3530        let result = parser.parse_function_annotations(source);
3531        assert!(result.is_ok());
3532    }
3533
3534    #[test]
3535    fn test_s12_parse_function_annotations_missing() {
3536        let parser = AnnotationParser::new();
3537        let source = r#"def process(data):
3538    return data
3539"#;
3540        let result = parser.parse_function_annotations(source);
3541        assert!(result.is_ok());
3542    }
3543}