1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
//! # Patch Application Engine
//!
//! This module provides the core patch application functionality that transforms
//! source code according to patches generated by macros. It supports multiple
//! patch types and generates bidirectional source mappings for IDE integration.
//!
//! ## Patch Types
//!
//! The engine supports five patch operations:
//!
//! | Type | Description |
//! |------|-------------|
//! | `Insert` | Insert formatted AST node at position |
//! | `InsertRaw` | Insert raw text at position |
//! | `Replace` | Replace span with formatted AST node |
//! | `ReplaceRaw` | Replace span with raw text |
//! | `Delete` | Remove span entirely |
//!
//! ## Application Strategy
//!
//! Patches are sorted by position and applied in forward order, with the
//! source mapping tracking position shifts:
//!
//! ```text
//! Original: "class Foo {}"
//! ^ Insert " bar: string;" at position 11
//!
//! Expanded: "class Foo { bar: string;}"
//!
//! Source Mapping:
//! Segment 1: original[0-11] -> expanded[0-11] (unchanged: "class Foo {")
//! Generated: expanded[11-25] = " bar: string;" (from macro "Test")
//! Segment 2: original[11-12] -> expanded[25-26] (unchanged: "}")
//! ```
//!
//! ## Position Conventions
//!
//! All [`SpanIR`] positions in patches use **1-based** byte offsets (matching SWC's
//! internal convention). The [`SourceMapping`] output uses **0-based** positions
//! (matching the TypeScript language service API). The applicator converts between
//! these conventions internally.
//!
//! ## Source Mapping
//!
//! The engine generates source mapping data that enables:
//! - Converting positions from original to expanded code
//! - Converting positions from expanded back to original
//! - Identifying which macro generated specific code regions
//! - Mapping IDE diagnostics to original source locations
//!
//! ## Example Usage
//!
//! ```rust,no_run
//! use macroforge_ts::host::patch_applicator::{PatchApplicator, PatchCollector};
//! use macroforge_ts::host::Result;
//! use macroforge_ts::ts_syn::abi::{Patch, SpanIR};
//!
//! fn example() -> Result<()> {
//! let source = "class Foo {}";
//!
//! // Using PatchApplicator directly
//! let patch = Patch::Insert {
//! at: SpanIR { start: 12, end: 12 }, // 1-based position
//! code: " bar: string;".into(),
//! source_macro: Some("Test".to_string()),
//! };
//!
//! let applicator = PatchApplicator::new(source, vec![patch]);
//! let result = applicator.apply_with_mapping(None)?;
//!
//! assert_eq!(result.code, "class Foo { bar: string;}");
//! assert!(!result.mapping.is_empty());
//!
//! // Using PatchCollector for multiple macros
//! let mut collector = PatchCollector::new();
//!
//! // Add patches from different macros
//! let debug_patch = Patch::Insert {
//! at: SpanIR { start: 12, end: 12 },
//! code: " toString() { return 'Foo'; }".into(),
//! source_macro: Some("Debug".to_string()),
//! };
//! collector.add_runtime_patches(vec![debug_patch]);
//!
//! // Apply all collected patches
//! let runtime_result = collector.apply_runtime_patches_with_mapping(source, None)?;
//! Ok(())
//! }
//! ```
pub use ;
pub use PatchCollector;