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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//! Helper utilities for working with patches and spans.
//!
//! This module provides convenience functions for common patching operations.
//! These helpers abstract away the details of span arithmetic and patch
//! construction for typical use cases.
//!
//! ## Common Operations
//!
//! | Function | Use Case |
//! |----------|----------|
//! | [`insert_into_class`] | Add a method or property to a class |
//! | [`insert_class_member`] | Insert an SWC ClassMember AST node |
//!
//! ## Example
//!
//! ```rust,no_run
//! use macroforge_ts_syn::{insert_into_class, ClassIR, MacroResult};
//!
//! fn generate_debug_method(class: &ClassIR) -> MacroResult {
//! let method = format!(
//! r#"debug(): string {{
//! return "{}";
//! }}"#,
//! class.name
//! );
//!
//! MacroResult {
//! runtime_patches: vec![insert_into_class(class.body_span, method)],
//! ..Default::default()
//! }
//! }
//! ```
use crate*;
/// Creates a patch to insert code inside a class body.
///
/// This helper calculates the correct insertion point (just before the
/// closing `}` brace) and creates an `Insert` patch. It's the recommended
/// way to add methods, properties, or other members to a class.
///
/// # Arguments
///
/// - `class_span` - The `body_span` of the class (from [`ClassIR::body_span`])
/// - `code` - The code to insert (string, `PatchCode`, or any type implementing `Into<PatchCode>`)
///
/// # Returns
///
/// A [`Patch::Insert`] positioned at `class_span.end - 1` (before the closing brace).
///
/// # Example
///
/// ```rust
/// use macroforge_ts_syn::{insert_into_class, Patch, SpanIR};
///
/// // Create a patch to insert code into a class body
/// let class_body_span = SpanIR::new(10, 50);
/// let _patch: Patch = insert_into_class(class_body_span, "toString() { return 'MyClass'; }");
///
/// // Given a class like:
/// // class Foo {
/// // name: string;
/// // }
/// //
/// // The patch inserts at position marked with |:
/// // class Foo {
/// // name: string;
/// // |
/// // }
/// ```
///
/// # Note
///
/// The `source_macro` field of the returned patch is `None`. Use
/// [`Patch::with_source_macro`] to set it for debugging purposes:
///
/// ```rust
/// use macroforge_ts_syn::{insert_into_class, SpanIR};
///
/// let class_body_span = SpanIR::new(10, 50);
/// let code = "toString() { return 'MyClass'; }";
/// let _patch = insert_into_class(class_body_span, code)
/// .with_source_macro("Debug");
/// ```
/// Creates a patch to insert an SWC `ClassMember` into a class body.
///
/// This is a convenience wrapper around [`insert_into_class`] that accepts
/// an SWC [`ClassMember`](swc_ast::ClassMember) AST node directly.
///
/// # Arguments
///
/// - `class_span` - The `body_span` of the class
/// - `member` - An SWC `ClassMember` (method, property, constructor, etc.)
///
/// # Example
///
/// ```rust,ignore
/// use macroforge_ts_syn::{insert_class_member, ts_ident, ClassIR};
/// use swc_core::ecma::ast::*;
/// use swc_core::common::DUMMY_SP;
///
/// fn add_property(class: &ClassIR) -> Patch {
/// let prop = ClassMember::ClassProp(ClassProp {
/// span: DUMMY_SP,
/// key: PropName::Ident(ts_ident!("generated")),
/// value: Some(Box::new(Expr::Lit(Lit::Bool(Bool {
/// span: DUMMY_SP,
/// value: true,
/// })))),
/// // ... other fields
/// });
///
/// insert_class_member(class.body_span, prop)
/// }
/// ```