Expand description
Patch application with source mapping.
§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:
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: "}")§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
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(())
}Structs§
- Apply
Result - Result of applying patches with source mapping
- Patch
Applicator - Applies patches to source code
- Patch
Collector - Builder for collecting and applying patches from multiple macros