@macroforge/mcp-server 0.1.39 → 0.1.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,242 +1,242 @@
1
1
  # ts_macro_derive
2
- *The `#[ts_macro_derive]` attribute is a Rust procedural macro that registers your function as a Macroforge derive macro.*
2
+ *The <code class="shiki-inline"><span class="line"><span style="--shiki-dark:#E1E4E8;--shiki-light:#24292E">#[ts_macro_derive]</code> attribute is a Rust procedural macro that registers your function as a Macroforge derive macro.*
3
3
  ## Basic Syntax
4
4
  ```
5
- use macroforge_ts::macros::ts_macro_derive;
6
- use macroforge_ts::ts_syn::&#123;TsStream, MacroforgeError&#125;;
5
+ use&nbsp;macroforge_ts::macros::ts_macro_derive;
6
+ use&nbsp;macroforge_ts::ts_syn::&#123;TsStream,&nbsp;MacroforgeError&#125;;
7
7
 
8
8
  #[ts_macro_derive(MacroName)]
9
- pub fn my_macro(mut input: TsStream) -> Result&#x3C;TsStream, MacroforgeError> &#123;
10
- // Macro implementation
9
+ pub&nbsp;fn&nbsp;my_macro(mut&nbsp;input:&nbsp;TsStream)&nbsp;->&nbsp;Result&#x3C;TsStream,&nbsp;MacroforgeError>&nbsp;&#123;
10
+ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Macro&nbsp;implementation
11
11
  &#125;
12
12
  ``` ## Attribute Options
13
13
  ### Name (Required)
14
- The first argument is the macro name that users will reference in `@derive()`:
14
+ The first argument is the macro name that users will reference in <code class="shiki-inline"><span class="line"><span style="--shiki-dark:#E1E4E8;--shiki-light:#24292E">@<span style="--shiki-dark:#B392F0;--shiki-light:#6F42C1">derive<span style="--shiki-dark:#E1E4E8;--shiki-light:#24292E">()</code>:
15
15
  ```
16
- #[ts_macro_derive(JSON)] // Users write: @derive(JSON)
17
- pub fn derive_json(...)
16
+ #[ts_macro_derive(JSON)]&nbsp;&nbsp;//&nbsp;Users&nbsp;write:&nbsp;@derive(JSON)
17
+ pub&nbsp;fn&nbsp;derive_json(...)
18
18
  ``` ### Description
19
19
  Provides documentation for the macro:
20
20
  ```
21
21
  #[ts_macro_derive(
22
- JSON,
23
- description = "Generates toJSON() returning a plain object"
22
+ &nbsp;&nbsp;&nbsp;&nbsp;JSON,
23
+ &nbsp;&nbsp;&nbsp;&nbsp;description&nbsp;=&nbsp;"Generates&nbsp;toJSON()&nbsp;returning&nbsp;a&nbsp;plain&nbsp;object"
24
24
  )]
25
- pub fn derive_json(...)
25
+ pub&nbsp;fn&nbsp;derive_json(...)
26
26
  ``` ### Attributes
27
27
  Declare which field-level decorators your macro accepts:
28
28
  ```
29
29
  #[ts_macro_derive(
30
- Debug,
31
- description = "Generates toString()",
32
- attributes(debug) // Allows @debug(&#123; ... &#125;) on fields
30
+ &nbsp;&nbsp;&nbsp;&nbsp;Debug,
31
+ &nbsp;&nbsp;&nbsp;&nbsp;description&nbsp;=&nbsp;"Generates&nbsp;toString()",
32
+ &nbsp;&nbsp;&nbsp;&nbsp;attributes(debug)&nbsp;&nbsp;//&nbsp;Allows&nbsp;@debug(&#123;&nbsp;...&nbsp;&#125;)&nbsp;on&nbsp;fields
33
33
  )]
34
- pub fn derive_debug(...)
34
+ pub&nbsp;fn&nbsp;derive_debug(...)
35
35
  ``` > **Note:** Declared attributes become available as @attributeName({ options }) decorators in TypeScript. ## Function Signature
36
36
  ```
37
- pub fn my_macro(mut input: TsStream) -> Result&#x3C;TsStream, MacroforgeError>
37
+ pub&nbsp;fn&nbsp;my_macro(mut&nbsp;input:&nbsp;TsStream)&nbsp;->&nbsp;Result&#x3C;TsStream,&nbsp;MacroforgeError>
38
38
  ``` | Parameter | Description |
39
39
  | --- | --- |
40
- | `input: TsStream` | Token stream containing the class/interface AST |
41
- | `Result<TsStream, MacroforgeError>` | Returns generated code or an error with source location |
40
+ | input: TsStream | Token stream containing the class/interface AST |
41
+ | Result<TsStream, MacroforgeError> | Returns generated code or an error with source location |
42
42
  ## Parsing Input
43
- Use `parse_ts_macro_input!` to convert the token stream:
43
+ Use <code class="shiki-inline"><span class="line"><span style="--shiki-dark:#B392F0;--shiki-light:#6F42C1">parse_ts_macro_input!</code> to convert the token stream:
44
44
  ```
45
- use macroforge_ts::ts_syn::&#123;Data, DeriveInput, parse_ts_macro_input&#125;;
45
+ use&nbsp;macroforge_ts::ts_syn::&#123;Data,&nbsp;DeriveInput,&nbsp;parse_ts_macro_input&#125;;
46
46
 
47
47
  #[ts_macro_derive(MyMacro)]
48
- pub fn my_macro(mut input: TsStream) -> Result&#x3C;TsStream, MacroforgeError> &#123;
49
- let input = parse_ts_macro_input!(input as DeriveInput);
50
-
51
- // Access class data
52
- match &#x26;input.data &#123;
53
- Data::Class(class) => &#123;
54
- let class_name = input.name();
55
- let fields = class.fields();
56
- // ...
57
- &#125;
58
- Data::Interface(interface) => &#123;
59
- // Handle interfaces
60
- &#125;
61
- Data::Enum(_) => &#123;
62
- // Handle enums (if supported)
63
- &#125;
64
- &#125;
48
+ pub&nbsp;fn&nbsp;my_macro(mut&nbsp;input:&nbsp;TsStream)&nbsp;->&nbsp;Result&#x3C;TsStream,&nbsp;MacroforgeError>&nbsp;&#123;
49
+ &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;input&nbsp;=&nbsp;parse_ts_macro_input!(input&nbsp;as&nbsp;DeriveInput);
50
+
51
+ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Access&nbsp;class&nbsp;data
52
+ &nbsp;&nbsp;&nbsp;&nbsp;match&nbsp;&#x26;input.data&nbsp;&#123;
53
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Data::Class(class)&nbsp;=>&nbsp;&#123;
54
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;class_name&nbsp;=&nbsp;input.name();
55
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;fields&nbsp;=&nbsp;class.fields();
56
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;...
57
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
58
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Data::Interface(interface)&nbsp;=>&nbsp;&#123;
59
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Handle&nbsp;interfaces
60
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
61
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Data::Enum(_)&nbsp;=>&nbsp;&#123;
62
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Handle&nbsp;enums&nbsp;(if&nbsp;supported)
63
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
64
+ &nbsp;&nbsp;&nbsp;&nbsp;&#125;
65
65
  &#125;
66
66
  ``` ## DeriveInput Structure
67
67
  ```
68
- struct DeriveInput &#123;
69
- pub ident: Ident, // The type name
70
- pub span: SpanIR, // Span of the type definition
71
- pub attrs: Vec&#x3C;Attribute>, // Decorators (excluding @derive)
72
- pub data: Data, // The parsed type data
73
- pub context: MacroContextIR, // Macro context with spans
74
-
75
- // Helper methods
76
- fn name(&#x26;self) -> &#x26;str; // Get the type name
77
- fn decorator_span(&#x26;self) -> SpanIR; // Span of @derive decorator
78
- fn as_class(&#x26;self) -> Option&#x3C;&#x26;DataClass>;
79
- fn as_interface(&#x26;self) -> Option&#x3C;&#x26;DataInterface>;
80
- fn as_enum(&#x26;self) -> Option&#x3C;&#x26;DataEnum>;
68
+ struct&nbsp;DeriveInput&nbsp;&#123;
69
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;ident:&nbsp;Ident,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;The&nbsp;type&nbsp;name
70
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;span:&nbsp;SpanIR,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Span&nbsp;of&nbsp;the&nbsp;type&nbsp;definition
71
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;attrs:&nbsp;Vec&#x3C;Attribute>,&nbsp;&nbsp;//&nbsp;Decorators&nbsp;(excluding&nbsp;@derive)
72
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;data:&nbsp;Data,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;The&nbsp;parsed&nbsp;type&nbsp;data
73
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;context:&nbsp;MacroContextIR,&nbsp;//&nbsp;Macro&nbsp;context&nbsp;with&nbsp;spans
74
+
75
+ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Helper&nbsp;methods
76
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;name(&#x26;self)&nbsp;->&nbsp;&#x26;str;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Get&nbsp;the&nbsp;type&nbsp;name
77
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;decorator_span(&#x26;self)&nbsp;->&nbsp;SpanIR;&nbsp;&nbsp;//&nbsp;Span&nbsp;of&nbsp;@derive&nbsp;decorator
78
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;as_class(&#x26;self)&nbsp;->&nbsp;Option&#x3C;&#x26;DataClass>;
79
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;as_interface(&#x26;self)&nbsp;->&nbsp;Option&#x3C;&#x26;DataInterface>;
80
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;as_enum(&#x26;self)&nbsp;->&nbsp;Option&#x3C;&#x26;DataEnum>;
81
81
  &#125;
82
82
 
83
- enum Data &#123;
84
- Class(DataClass),
85
- Interface(DataInterface),
86
- Enum(DataEnum),
87
- TypeAlias(DataTypeAlias),
83
+ enum&nbsp;Data&nbsp;&#123;
84
+ &nbsp;&nbsp;&nbsp;&nbsp;Class(DataClass),
85
+ &nbsp;&nbsp;&nbsp;&nbsp;Interface(DataInterface),
86
+ &nbsp;&nbsp;&nbsp;&nbsp;Enum(DataEnum),
87
+ &nbsp;&nbsp;&nbsp;&nbsp;TypeAlias(DataTypeAlias),
88
88
  &#125;
89
89
 
90
- impl DataClass &#123;
91
- fn fields(&#x26;self) -> &#x26;[FieldIR];
92
- fn methods(&#x26;self) -> &#x26;[MethodSigIR];
93
- fn field_names(&#x26;self) -> impl Iterator&#x3C;Item = &#x26;str>;
94
- fn field(&#x26;self, name: &#x26;str) -> Option&#x3C;&#x26;FieldIR>;
95
- fn body_span(&#x26;self) -> SpanIR; // For inserting code into class body
96
- fn type_params(&#x26;self) -> &#x26;[String]; // Generic type parameters
97
- fn heritage(&#x26;self) -> &#x26;[String]; // extends/implements clauses
98
- fn is_abstract(&#x26;self) -> bool;
90
+ impl&nbsp;DataClass&nbsp;&#123;
91
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;fields(&#x26;self)&nbsp;->&nbsp;&#x26;[FieldIR];
92
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;methods(&#x26;self)&nbsp;->&nbsp;&#x26;[MethodSigIR];
93
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;field_names(&#x26;self)&nbsp;->&nbsp;impl&nbsp;Iterator&#x3C;Item&nbsp;=&nbsp;&#x26;str>;
94
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;field(&#x26;self,&nbsp;name:&nbsp;&#x26;str)&nbsp;->&nbsp;Option&#x3C;&#x26;FieldIR>;
95
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;body_span(&#x26;self)&nbsp;->&nbsp;SpanIR;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;For&nbsp;inserting&nbsp;code&nbsp;into&nbsp;class&nbsp;body
96
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;type_params(&#x26;self)&nbsp;->&nbsp;&#x26;[String];&nbsp;//&nbsp;Generic&nbsp;type&nbsp;parameters
97
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;heritage(&#x26;self)&nbsp;->&nbsp;&#x26;[String];&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;extends/implements&nbsp;clauses
98
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;is_abstract(&#x26;self)&nbsp;->&nbsp;bool;
99
99
  &#125;
100
100
 
101
- impl DataInterface &#123;
102
- fn fields(&#x26;self) -> &#x26;[InterfaceFieldIR];
103
- fn methods(&#x26;self) -> &#x26;[InterfaceMethodIR];
104
- fn field_names(&#x26;self) -> impl Iterator&#x3C;Item = &#x26;str>;
105
- fn field(&#x26;self, name: &#x26;str) -> Option&#x3C;&#x26;InterfaceFieldIR>;
106
- fn body_span(&#x26;self) -> SpanIR;
107
- fn type_params(&#x26;self) -> &#x26;[String];
108
- fn heritage(&#x26;self) -> &#x26;[String]; // extends clauses
101
+ impl&nbsp;DataInterface&nbsp;&#123;
102
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;fields(&#x26;self)&nbsp;->&nbsp;&#x26;[InterfaceFieldIR];
103
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;methods(&#x26;self)&nbsp;->&nbsp;&#x26;[InterfaceMethodIR];
104
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;field_names(&#x26;self)&nbsp;->&nbsp;impl&nbsp;Iterator&#x3C;Item&nbsp;=&nbsp;&#x26;str>;
105
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;field(&#x26;self,&nbsp;name:&nbsp;&#x26;str)&nbsp;->&nbsp;Option&#x3C;&#x26;InterfaceFieldIR>;
106
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;body_span(&#x26;self)&nbsp;->&nbsp;SpanIR;
107
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;type_params(&#x26;self)&nbsp;->&nbsp;&#x26;[String];
108
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;heritage(&#x26;self)&nbsp;->&nbsp;&#x26;[String];&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;extends&nbsp;clauses
109
109
  &#125;
110
110
 
111
- impl DataEnum &#123;
112
- fn variants(&#x26;self) -> &#x26;[EnumVariantIR];
113
- fn variant_names(&#x26;self) -> impl Iterator&#x3C;Item = &#x26;str>;
114
- fn variant(&#x26;self, name: &#x26;str) -> Option&#x3C;&#x26;EnumVariantIR>;
111
+ impl&nbsp;DataEnum&nbsp;&#123;
112
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;variants(&#x26;self)&nbsp;->&nbsp;&#x26;[EnumVariantIR];
113
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;variant_names(&#x26;self)&nbsp;->&nbsp;impl&nbsp;Iterator&#x3C;Item&nbsp;=&nbsp;&#x26;str>;
114
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;variant(&#x26;self,&nbsp;name:&nbsp;&#x26;str)&nbsp;->&nbsp;Option&#x3C;&#x26;EnumVariantIR>;
115
115
  &#125;
116
116
 
117
- impl DataTypeAlias &#123;
118
- fn body(&#x26;self) -> &#x26;TypeBody;
119
- fn type_params(&#x26;self) -> &#x26;[String];
120
- fn is_union(&#x26;self) -> bool;
121
- fn is_object(&#x26;self) -> bool;
122
- fn as_union(&#x26;self) -> Option&#x3C;&#x26;[TypeMember]>;
123
- fn as_object(&#x26;self) -> Option&#x3C;&#x26;[InterfaceFieldIR]>;
117
+ impl&nbsp;DataTypeAlias&nbsp;&#123;
118
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;body(&#x26;self)&nbsp;->&nbsp;&#x26;TypeBody;
119
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;type_params(&#x26;self)&nbsp;->&nbsp;&#x26;[String];
120
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;is_union(&#x26;self)&nbsp;->&nbsp;bool;
121
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;is_object(&#x26;self)&nbsp;->&nbsp;bool;
122
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;as_union(&#x26;self)&nbsp;->&nbsp;Option&#x3C;&#x26;[TypeMember]>;
123
+ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;as_object(&#x26;self)&nbsp;->&nbsp;Option&#x3C;&#x26;[InterfaceFieldIR]>;
124
124
  &#125;
125
125
  ``` ## Accessing Field Data
126
126
  ### Class Fields (FieldIR)
127
127
  ```
128
- struct FieldIR &#123;
129
- pub name: String, // Field name
130
- pub span: SpanIR, // Field span
131
- pub ts_type: String, // TypeScript type annotation
132
- pub optional: bool, // Whether field has ?
133
- pub readonly: bool, // Whether field is readonly
134
- pub visibility: Visibility, // Public, Protected, Private
135
- pub decorators: Vec&#x3C;DecoratorIR>, // Field decorators
128
+ struct&nbsp;FieldIR&nbsp;&#123;
129
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;name:&nbsp;String,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Field&nbsp;name
130
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;span:&nbsp;SpanIR,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Field&nbsp;span
131
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;ts_type:&nbsp;String,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;TypeScript&nbsp;type&nbsp;annotation
132
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;optional:&nbsp;bool,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Whether&nbsp;field&nbsp;has&nbsp;?
133
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;readonly:&nbsp;bool,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Whether&nbsp;field&nbsp;is&nbsp;readonly
134
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;visibility:&nbsp;Visibility,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Public,&nbsp;Protected,&nbsp;Private
135
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;decorators:&nbsp;Vec&#x3C;DecoratorIR>,&nbsp;//&nbsp;Field&nbsp;decorators
136
136
  &#125;
137
137
  ``` ### Interface Fields (InterfaceFieldIR)
138
138
  ```
139
- struct InterfaceFieldIR &#123;
140
- pub name: String,
141
- pub span: SpanIR,
142
- pub ts_type: String,
143
- pub optional: bool,
144
- pub readonly: bool,
145
- pub decorators: Vec&#x3C;DecoratorIR>,
146
- // Note: No visibility field (interfaces are always public)
139
+ struct&nbsp;InterfaceFieldIR&nbsp;&#123;
140
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;name:&nbsp;String,
141
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;span:&nbsp;SpanIR,
142
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;ts_type:&nbsp;String,
143
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;optional:&nbsp;bool,
144
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;readonly:&nbsp;bool,
145
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;decorators:&nbsp;Vec&#x3C;DecoratorIR>,
146
+ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Note:&nbsp;No&nbsp;visibility&nbsp;field&nbsp;(interfaces&nbsp;are&nbsp;always&nbsp;public)
147
147
  &#125;
148
148
  ``` ### Enum Variants (EnumVariantIR)
149
149
  ```
150
- struct EnumVariantIR &#123;
151
- pub name: String,
152
- pub span: SpanIR,
153
- pub value: EnumValue, // Auto, String(String), or Number(f64)
154
- pub decorators: Vec&#x3C;DecoratorIR>,
150
+ struct&nbsp;EnumVariantIR&nbsp;&#123;
151
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;name:&nbsp;String,
152
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;span:&nbsp;SpanIR,
153
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;value:&nbsp;EnumValue,&nbsp;&nbsp;//&nbsp;Auto,&nbsp;String(String),&nbsp;or&nbsp;Number(f64)
154
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;decorators:&nbsp;Vec&#x3C;DecoratorIR>,
155
155
  &#125;
156
156
  ``` ### Decorator Structure
157
157
  ```
158
- struct DecoratorIR &#123;
159
- pub name: String, // e.g., "serde"
160
- pub args_src: String, // Raw args text, e.g., "skip, rename: 'id'"
161
- pub span: SpanIR,
158
+ struct&nbsp;DecoratorIR&nbsp;&#123;
159
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;name:&nbsp;String,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;e.g.,&nbsp;"serde"
160
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;args_src:&nbsp;String,&nbsp;&nbsp;//&nbsp;Raw&nbsp;args&nbsp;text,&nbsp;e.g.,&nbsp;"skip,&nbsp;rename:&nbsp;'id'"
161
+ &nbsp;&nbsp;&nbsp;&nbsp;pub&nbsp;span:&nbsp;SpanIR,
162
162
  &#125;
163
163
  ``` > **Note:** To check for decorators, iterate through field.decorators and check decorator.name. For parsing options, you can write helper functions like the built-in macros do. ## Adding Imports
164
- If your macro generates code that requires imports, use the `add_import` method on `TsStream`:
164
+ If your macro generates code that requires imports, use the <code class="shiki-inline"><span class="line"><span style="--shiki-dark:#E1E4E8;--shiki-light:#24292E">add_import</code> method on <code class="shiki-inline"><span class="line"><span style="--shiki-dark:#E1E4E8;--shiki-light:#24292E">TsStream</code>:
165
165
  ```
166
- // Add an import to be inserted at the top of the file
167
- let mut output = body! &#123;
168
- validate(): ValidationResult &#123;
169
- return validateFields(this);
170
- &#125;
166
+ //&nbsp;Add&nbsp;an&nbsp;import&nbsp;to&nbsp;be&nbsp;inserted&nbsp;at&nbsp;the&nbsp;top&nbsp;of&nbsp;the&nbsp;file
167
+ let&nbsp;mut&nbsp;output&nbsp;=&nbsp;body!&nbsp;&#123;
168
+ &nbsp;&nbsp;&nbsp;&nbsp;validate():&nbsp;ValidationResult&nbsp;&#123;
169
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;validateFields(this);
170
+ &nbsp;&nbsp;&nbsp;&nbsp;&#125;
171
171
  &#125;;
172
172
 
173
- // This will add: import &#123; validateFields, ValidationResult &#125; from "my-validation-lib";
174
- output.add_import("validateFields", "my-validation-lib");
175
- output.add_import("ValidationResult", "my-validation-lib");
173
+ //&nbsp;This&nbsp;will&nbsp;add:&nbsp;import&nbsp;&#123;&nbsp;validateFields,&nbsp;ValidationResult&nbsp;&#125;&nbsp;from&nbsp;"my-validation-lib";
174
+ output.add_import("validateFields",&nbsp;"my-validation-lib");
175
+ output.add_import("ValidationResult",&nbsp;"my-validation-lib");
176
176
 
177
177
  Ok(output)
178
178
  ``` > **Note:** Imports are automatically deduplicated. If the same import already exists in the file, it won't be added again. ## Returning Errors
179
- Use `MacroforgeError` to report errors with source locations:
179
+ Use <code class="shiki-inline"><span class="line"><span style="--shiki-dark:#E1E4E8;--shiki-light:#24292E">MacroforgeError</code> to report errors with source locations:
180
180
  ```
181
181
  #[ts_macro_derive(ClassOnly)]
182
- pub fn class_only(mut input: TsStream) -> Result&#x3C;TsStream, MacroforgeError> &#123;
183
- let input = parse_ts_macro_input!(input as DeriveInput);
184
-
185
- match &#x26;input.data &#123;
186
- Data::Class(_) => &#123;
187
- // Generate code...
188
- Ok(body! &#123; /* ... */ &#125;)
189
- &#125;
190
- _ => Err(MacroforgeError::new(
191
- input.decorator_span(),
192
- "@derive(ClassOnly) can only be used on classes",
193
- )),
194
- &#125;
182
+ pub&nbsp;fn&nbsp;class_only(mut&nbsp;input:&nbsp;TsStream)&nbsp;->&nbsp;Result&#x3C;TsStream,&nbsp;MacroforgeError>&nbsp;&#123;
183
+ &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;input&nbsp;=&nbsp;parse_ts_macro_input!(input&nbsp;as&nbsp;DeriveInput);
184
+
185
+ &nbsp;&nbsp;&nbsp;&nbsp;match&nbsp;&#x26;input.data&nbsp;&#123;
186
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Data::Class(_)&nbsp;=>&nbsp;&#123;
187
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Generate&nbsp;code...
188
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ok(body!&nbsp;&#123;&nbsp;/*&nbsp;...&nbsp;*/&nbsp;&#125;)
189
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
190
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_&nbsp;=>&nbsp;Err(MacroforgeError::new(
191
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input.decorator_span(),
192
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"@derive(ClassOnly)&nbsp;can&nbsp;only&nbsp;be&nbsp;used&nbsp;on&nbsp;classes",
193
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)),
194
+ &nbsp;&nbsp;&nbsp;&nbsp;&#125;
195
195
  &#125;
196
196
  ``` ## Complete Example
197
197
  ```
198
- use macroforge_ts::macros::&#123;ts_macro_derive, body&#125;;
199
- use macroforge_ts::ts_syn::&#123;
200
- Data, DeriveInput, FieldIR, MacroforgeError, TsStream, parse_ts_macro_input,
198
+ use&nbsp;macroforge_ts::macros::&#123;ts_macro_derive,&nbsp;body&#125;;
199
+ use&nbsp;macroforge_ts::ts_syn::&#123;
200
+ &nbsp;&nbsp;&nbsp;&nbsp;Data,&nbsp;DeriveInput,&nbsp;FieldIR,&nbsp;MacroforgeError,&nbsp;TsStream,&nbsp;parse_ts_macro_input,
201
201
  &#125;;
202
202
 
203
- // Helper function to check if a field has a decorator
204
- fn has_decorator(field: &#x26;FieldIR, name: &#x26;str) -> bool &#123;
205
- field.decorators.iter().any(|d| d.name.eq_ignore_ascii_case(name))
203
+ //&nbsp;Helper&nbsp;function&nbsp;to&nbsp;check&nbsp;if&nbsp;a&nbsp;field&nbsp;has&nbsp;a&nbsp;decorator
204
+ fn&nbsp;has_decorator(field:&nbsp;&#x26;FieldIR,&nbsp;name:&nbsp;&#x26;str)&nbsp;->&nbsp;bool&nbsp;&#123;
205
+ &nbsp;&nbsp;&nbsp;&nbsp;field.decorators.iter().any(|d|&nbsp;d.name.eq_ignore_ascii_case(name))
206
206
  &#125;
207
207
 
208
208
  #[ts_macro_derive(
209
- Validate,
210
- description = "Generates a validate() method",
211
- attributes(validate)
209
+ &nbsp;&nbsp;&nbsp;&nbsp;Validate,
210
+ &nbsp;&nbsp;&nbsp;&nbsp;description&nbsp;=&nbsp;"Generates&nbsp;a&nbsp;validate()&nbsp;method",
211
+ &nbsp;&nbsp;&nbsp;&nbsp;attributes(validate)
212
212
  )]
213
- pub fn derive_validate(mut input: TsStream) -> Result&#x3C;TsStream, MacroforgeError> &#123;
214
- let input = parse_ts_macro_input!(input as DeriveInput);
215
-
216
- match &#x26;input.data &#123;
217
- Data::Class(class) => &#123;
218
- let validations: Vec&#x3C;_> = class.fields()
219
- .iter()
220
- .filter(|f| has_decorator(f, "validate"))
221
- .collect();
222
-
223
- Ok(body! &#123;
224
- validate(): string[] &#123;
225
- const errors: string[] = [];
226
- &#123;#for field in validations&#125;
227
- if (!this.@&#123;field.name&#125;) &#123;
228
- errors.push("@&#123;field.name&#125; is required");
229
- &#125;
230
- &#123;/for&#125;
231
- return errors;
232
- &#125;
233
- &#125;)
234
- &#125;
235
- _ => Err(MacroforgeError::new(
236
- input.decorator_span(),
237
- "@derive(Validate) only works on classes",
238
- )),
239
- &#125;
213
+ pub&nbsp;fn&nbsp;derive_validate(mut&nbsp;input:&nbsp;TsStream)&nbsp;->&nbsp;Result&#x3C;TsStream,&nbsp;MacroforgeError>&nbsp;&#123;
214
+ &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;input&nbsp;=&nbsp;parse_ts_macro_input!(input&nbsp;as&nbsp;DeriveInput);
215
+
216
+ &nbsp;&nbsp;&nbsp;&nbsp;match&nbsp;&#x26;input.data&nbsp;&#123;
217
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Data::Class(class)&nbsp;=>&nbsp;&#123;
218
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;validations:&nbsp;Vec&#x3C;_>&nbsp;=&nbsp;class.fields()
219
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.iter()
220
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.filter(|f|&nbsp;has_decorator(f,&nbsp;"validate"))
221
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.collect();
222
+
223
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ok(body!&nbsp;&#123;
224
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;validate():&nbsp;string[]&nbsp;&#123;
225
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;errors:&nbsp;string[]&nbsp;=&nbsp;[];
226
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;#for&nbsp;field&nbsp;in&nbsp;validations&#125;
227
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!this.@&#123;field.name&#125;)&nbsp;&#123;
228
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;errors.push("@&#123;field.name&#125;&nbsp;is&nbsp;required");
229
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
230
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;/for&#125;
231
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;errors;
232
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
233
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;)
234
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
235
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_&nbsp;=>&nbsp;Err(MacroforgeError::new(
236
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input.decorator_span(),
237
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"@derive(Validate)&nbsp;only&nbsp;works&nbsp;on&nbsp;classes",
238
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)),
239
+ &nbsp;&nbsp;&nbsp;&nbsp;&#125;
240
240
  &#125;
241
241
  ``` ## Next Steps
242
242
  - [Learn the template syntax](../../docs/custom-macros/ts-quote)