@macroforge/mcp-server 0.1.40 → 0.1.49
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.
- package/LICENSE +22 -0
- package/docs/BOOK.md +165 -0
- package/docs/api/api-overview.md +65 -46
- package/docs/api/expand-sync.md +88 -53
- package/docs/api/native-plugin.md +121 -71
- package/docs/api/position-mapper.md +114 -54
- package/docs/api/transform-sync.md +85 -59
- package/docs/builtin-macros/clone.md +0 -20
- package/docs/builtin-macros/debug.md +0 -23
- package/docs/builtin-macros/default.md +1 -40
- package/docs/builtin-macros/deserialize/example.md +8 -1416
- package/docs/builtin-macros/deserialize.md +8 -1416
- package/docs/builtin-macros/hash.md +0 -42
- package/docs/builtin-macros/macros-overview/detailed-documentation.md +13 -0
- package/docs/builtin-macros/macros-overview/enum-support.md +30 -0
- package/docs/builtin-macros/macros-overview/interface-support.md +28 -0
- package/docs/builtin-macros/macros-overview/overview.md +36 -0
- package/docs/builtin-macros/macros-overview/type-alias-support.md +62 -0
- package/docs/builtin-macros/macros-overview.md +171 -130
- package/docs/builtin-macros/ord.md +0 -25
- package/docs/builtin-macros/partial-eq.md +0 -84
- package/docs/builtin-macros/partial-ord.md +11 -43
- package/docs/builtin-macros/serialize.md +2 -62
- package/docs/concepts/architecture.md +125 -48
- package/docs/concepts/derive-system/built-in-vs-custom-macros.md +13 -0
- package/docs/concepts/derive-system/overview.md +200 -0
- package/docs/concepts/derive-system.md +171 -97
- package/docs/concepts/how-macros-work.md +89 -37
- package/docs/custom-macros/custom-overview.md +79 -57
- package/docs/custom-macros/rust-setup.md +138 -99
- package/docs/custom-macros/ts-macro-derive/accessing-field-data.md +40 -31
- package/docs/custom-macros/ts-macro-derive/adding-imports.md +14 -11
- package/docs/custom-macros/ts-macro-derive/attribute-options.md +20 -25
- package/docs/custom-macros/ts-macro-derive/complete-example.md +40 -38
- package/docs/custom-macros/ts-macro-derive/deriveinput-structure.md +49 -47
- package/docs/custom-macros/ts-macro-derive/function-signature.md +12 -0
- package/docs/custom-macros/ts-macro-derive/overview.md +9 -7
- package/docs/custom-macros/ts-macro-derive/parsing-input.md +20 -18
- package/docs/custom-macros/ts-macro-derive/returning-errors.md +15 -13
- package/docs/custom-macros/ts-macro-derive.md +322 -228
- package/docs/custom-macros/ts-quote/backtick-template-literals.md +19 -7
- package/docs/custom-macros/ts-quote/comments-and.md +56 -22
- package/docs/custom-macros/ts-quote/complete-example-json-derive-macro.md +89 -98
- package/docs/custom-macros/ts-quote/conditionals-ifif.md +35 -29
- package/docs/custom-macros/ts-quote/identifier-concatenation-content.md +30 -22
- package/docs/custom-macros/ts-quote/iteration-for.md +48 -40
- package/docs/custom-macros/ts-quote/local-constants-let.md +23 -21
- package/docs/custom-macros/ts-quote/match-expressions-match.md +46 -38
- package/docs/custom-macros/ts-quote/overview.md +5 -10
- package/docs/custom-macros/ts-quote/pattern-matching-iflet.md +39 -0
- package/docs/custom-macros/ts-quote/quick-reference.md +50 -129
- package/docs/custom-macros/ts-quote/side-effects-do.md +13 -78
- package/docs/custom-macros/ts-quote/string-interpolation-textexpr.md +36 -0
- package/docs/custom-macros/ts-quote/tsstream-injection-typescript.md +43 -35
- package/docs/custom-macros/ts-quote/while-loops-while.md +31 -23
- package/docs/custom-macros/ts-quote.md +799 -519
- package/docs/getting-started/first-macro.md +61 -32
- package/docs/getting-started/installation.md +109 -66
- package/docs/integration/cli.md +212 -103
- package/docs/integration/configuration.md +114 -71
- package/docs/integration/integration-overview.md +54 -17
- package/docs/integration/mcp-server.md +83 -42
- package/docs/integration/svelte-preprocessor.md +183 -126
- package/docs/integration/typescript-plugin.md +101 -54
- package/docs/integration/vite-plugin.md +116 -76
- package/docs/language-servers/ls-overview.md +37 -21
- package/docs/language-servers/svelte.md +69 -39
- package/docs/language-servers/zed.md +81 -45
- package/docs/roadmap/roadmap.md +75 -53
- package/docs/sections.json +333 -44
- package/package.json +27 -28
|
@@ -99,48 +99,6 @@ export function userEquals(a: User, b: User): boolean {
|
|
|
99
99
|
}
|
|
100
100
|
```
|
|
101
101
|
|
|
102
|
-
Generated output:
|
|
103
|
-
|
|
104
|
-
```typescript
|
|
105
|
-
class User {
|
|
106
|
-
id: number;
|
|
107
|
-
name: string;
|
|
108
|
-
|
|
109
|
-
cachedScore: number;
|
|
110
|
-
|
|
111
|
-
static hashCode(value: User): number {
|
|
112
|
-
return userHashCode(value);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
static equals(a: User, b: User): boolean {
|
|
116
|
-
return userEquals(a, b);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export function userHashCode(value: User): number {
|
|
121
|
-
let hash = 17;
|
|
122
|
-
hash =
|
|
123
|
-
(hash * 31 +
|
|
124
|
-
(Number.isInteger(value.id)
|
|
125
|
-
? value.id | 0
|
|
126
|
-
: value.id
|
|
127
|
-
.toString()
|
|
128
|
-
.split('')
|
|
129
|
-
.reduce((h, c) => (h * 31 + c.charCodeAt(0)) | 0, 0))) |
|
|
130
|
-
0;
|
|
131
|
-
hash =
|
|
132
|
-
(hash * 31 +
|
|
133
|
-
(value.name ?? '').split('').reduce((h, c) => (h * 31 + c.charCodeAt(0)) | 0, 0)) |
|
|
134
|
-
0;
|
|
135
|
-
return hash;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export function userEquals(a: User, b: User): boolean {
|
|
139
|
-
if (a === b) return true;
|
|
140
|
-
return a.id === b.id && a.name === b.name && a.cachedScore === b.cachedScore;
|
|
141
|
-
}
|
|
142
|
-
```
|
|
143
|
-
|
|
144
102
|
## Hash Contract
|
|
145
103
|
|
|
146
104
|
Objects that are equal (`PartialEq`) should produce the same hash code.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
## Detailed Documentation
|
|
2
|
+
|
|
3
|
+
Each macro has its own options and behaviors:
|
|
4
|
+
|
|
5
|
+
* [**Debug**](../docs/builtin-macros/debug) - Customizable field renaming and skipping
|
|
6
|
+
* [**Clone**](../docs/builtin-macros/clone) - Deep copying for all field types
|
|
7
|
+
* [**Default**](../docs/builtin-macros/default) - Default value generation with field attributes
|
|
8
|
+
* [**Hash**](../docs/builtin-macros/hash) - Hash code generation for use in maps and sets
|
|
9
|
+
* [**PartialEq**](../docs/builtin-macros/partial-eq) - Value-based equality comparison
|
|
10
|
+
* [**Ord**](../docs/builtin-macros/ord) - Total ordering for sorting
|
|
11
|
+
* [**PartialOrd**](../docs/builtin-macros/partial-ord) - Partial ordering comparison
|
|
12
|
+
* [**Serialize**](../docs/builtin-macros/serialize) - JSON serialization with serde-style options
|
|
13
|
+
* [**Deserialize**](../docs/builtin-macros/deserialize) - JSON deserialization with validation
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
## Enum Support
|
|
2
|
+
|
|
3
|
+
All built-in macros work with enums. For enums, methods are generated as functions in a namespace with the same name:
|
|
4
|
+
|
|
5
|
+
TypeScript
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
/** @derive(Debug, Clone, PartialEq, Serialize, Deserialize) */
|
|
9
|
+
enum Status {
|
|
10
|
+
Active = "active",
|
|
11
|
+
Inactive = "inactive",
|
|
12
|
+
Pending = "pending",
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Generated namespace:
|
|
16
|
+
// namespace Status {
|
|
17
|
+
// export function toString(value: Status): string { ... }
|
|
18
|
+
// export function clone(value: Status): Status { ... }
|
|
19
|
+
// export function equals(a: Status, b: Status): boolean { ... }
|
|
20
|
+
// export function hashCode(value: Status): number { ... }
|
|
21
|
+
// export function toJSON(value: Status): string | number { ... }
|
|
22
|
+
// export function fromJSON(data: unknown): Status { ... }
|
|
23
|
+
// }
|
|
24
|
+
|
|
25
|
+
// Use the namespace functions
|
|
26
|
+
console.log(Status.toString(Status.Active)); // "Status.Active"
|
|
27
|
+
console.log(Status.equals(Status.Active, Status.Active)); // true
|
|
28
|
+
const json = Status.toJSON(Status.Pending); // "pending"
|
|
29
|
+
const parsed = Status.fromJSON("active"); // Status.Active
|
|
30
|
+
```
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
## Interface Support
|
|
2
|
+
|
|
3
|
+
All built-in macros work with interfaces. For interfaces, methods are generated as functions in a namespace with the same name, using `self` as the first parameter:
|
|
4
|
+
|
|
5
|
+
TypeScript
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
/** @derive(Debug, Clone, PartialEq) */
|
|
9
|
+
interface Point {
|
|
10
|
+
x: number;
|
|
11
|
+
y: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Generated namespace:
|
|
15
|
+
// namespace Point {
|
|
16
|
+
// export function toString(self: Point): string { ... }
|
|
17
|
+
// export function clone(self: Point): Point { ... }
|
|
18
|
+
// export function equals(self: Point, other: Point): boolean { ... }
|
|
19
|
+
// export function hashCode(self: Point): number { ... }
|
|
20
|
+
// }
|
|
21
|
+
|
|
22
|
+
const point: Point = { x: 10, y: 20 };
|
|
23
|
+
|
|
24
|
+
// Use the namespace functions
|
|
25
|
+
console.log(Point.toString(point)); // "Point { x: 10, y: 20 }"
|
|
26
|
+
const copy = Point.clone(point); // { x: 10, y: 20 }
|
|
27
|
+
console.log(Point.equals(point, copy)); // true
|
|
28
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Built-in Macros
|
|
2
|
+
|
|
3
|
+
Macroforge comes with built-in derive macros that cover the most common code generation needs. All macros work with classes, interfaces, enums, and type aliases.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
| Macro | Generates | Description |
|
|
8
|
+
| --------------------------------------------------- | ----------------------------------------- | --------------------------------------- |
|
|
9
|
+
| [`Debug`](../docs/builtin-macros/debug) | `toString(): string` | Human-readable string representation |
|
|
10
|
+
| [`Clone`](../docs/builtin-macros/clone) | `clone(): T` | Creates a deep copy of the object |
|
|
11
|
+
| [`Default`](../docs/builtin-macros/default) | `static default(): T` | Creates an instance with default values |
|
|
12
|
+
| [`Hash`](../docs/builtin-macros/hash) | `hashCode(): number` | Generates a hash code for the object |
|
|
13
|
+
| [`PartialEq`](../docs/builtin-macros/partial-eq) | `equals(other: T): boolean` | Value equality comparison |
|
|
14
|
+
| [`Ord`](../docs/builtin-macros/ord) | `compare(other: T): number` | Total ordering comparison (-1, 0, 1) |
|
|
15
|
+
| [`PartialOrd`](../docs/builtin-macros/partial-ord) | `partialCompare(other: T): number | null` | Partial ordering comparison |
|
|
16
|
+
| [`Serialize`](../docs/builtin-macros/serialize) | `toJSON(): Record<string, unknown>` | JSON serialization with type handling |
|
|
17
|
+
| [`Deserialize`](../docs/builtin-macros/deserialize) | `static fromJSON(data: unknown): T` | JSON deserialization with validation |
|
|
18
|
+
|
|
19
|
+
## Using Built-in Macros
|
|
20
|
+
|
|
21
|
+
Built-in macros don't require imports. Just use them with `@derive`:
|
|
22
|
+
|
|
23
|
+
TypeScript
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
/** @derive(Debug, Clone, PartialEq) */
|
|
27
|
+
class User {
|
|
28
|
+
name: string;
|
|
29
|
+
age: number;
|
|
30
|
+
|
|
31
|
+
constructor(name: string, age: number) {
|
|
32
|
+
this.name = name;
|
|
33
|
+
this.age = age;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
## Type Alias Support
|
|
2
|
+
|
|
3
|
+
All built-in macros work with type aliases. For object type aliases, field-aware methods are generated in a namespace:
|
|
4
|
+
|
|
5
|
+
TypeScript
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
/** @derive(Debug, Clone, PartialEq, Serialize, Deserialize) */
|
|
9
|
+
type Point = {
|
|
10
|
+
x: number;
|
|
11
|
+
y: number;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
// Generated namespace:
|
|
15
|
+
// namespace Point {
|
|
16
|
+
// export function toString(value: Point): string { ... }
|
|
17
|
+
// export function clone(value: Point): Point { ... }
|
|
18
|
+
// export function equals(a: Point, b: Point): boolean { ... }
|
|
19
|
+
// export function hashCode(value: Point): number { ... }
|
|
20
|
+
// export function toJSON(value: Point): Record<string, unknown> { ... }
|
|
21
|
+
// export function fromJSON(data: unknown): Point { ... }
|
|
22
|
+
// }
|
|
23
|
+
|
|
24
|
+
const point: Point = { x: 10, y: 20 };
|
|
25
|
+
console.log(Point.toString(point)); // "Point { x: 10, y: 20 }"
|
|
26
|
+
const copy = Point.clone(point); // { x: 10, y: 20 }
|
|
27
|
+
console.log(Point.equals(point, copy)); // true
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Union type aliases also work, using JSON-based implementations:
|
|
31
|
+
|
|
32
|
+
TypeScript
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
/** @derive(Debug, PartialEq) */
|
|
36
|
+
type ApiStatus = "loading" | "success" | "error";
|
|
37
|
+
|
|
38
|
+
const status: ApiStatus = "success";
|
|
39
|
+
console.log(ApiStatus.toString(status)); // "ApiStatus(\\"success\\")"
|
|
40
|
+
console.log(ApiStatus.equals("success", "success")); // true
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Combining Macros
|
|
44
|
+
|
|
45
|
+
All macros can be used together. They don't conflict and each generates independent methods:
|
|
46
|
+
|
|
47
|
+
TypeScript
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
const user = new User("Alice", 30);
|
|
51
|
+
|
|
52
|
+
// Debug
|
|
53
|
+
console.log(user.toString());
|
|
54
|
+
// "User { name: Alice, age: 30 }"
|
|
55
|
+
|
|
56
|
+
// Clone
|
|
57
|
+
const copy = user.clone();
|
|
58
|
+
console.log(copy.name); // "Alice"
|
|
59
|
+
|
|
60
|
+
// Eq
|
|
61
|
+
console.log(user.equals(copy)); // true
|
|
62
|
+
```
|
|
@@ -1,132 +1,173 @@
|
|
|
1
1
|
# Built-in Macros
|
|
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
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
//
|
|
2
|
+
|
|
3
|
+
Macroforge comes with built-in derive macros that cover the most common code generation needs. All macros work with classes, interfaces, enums, and type aliases.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
| Macro | Generates | Description |
|
|
8
|
+
| --------------------------------------------------- | ----------------------------------------- | --------------------------------------- |
|
|
9
|
+
| [`Debug`](../docs/builtin-macros/debug) | `toString(): string` | Human-readable string representation |
|
|
10
|
+
| [`Clone`](../docs/builtin-macros/clone) | `clone(): T` | Creates a deep copy of the object |
|
|
11
|
+
| [`Default`](../docs/builtin-macros/default) | `static default(): T` | Creates an instance with default values |
|
|
12
|
+
| [`Hash`](../docs/builtin-macros/hash) | `hashCode(): number` | Generates a hash code for the object |
|
|
13
|
+
| [`PartialEq`](../docs/builtin-macros/partial-eq) | `equals(other: T): boolean` | Value equality comparison |
|
|
14
|
+
| [`Ord`](../docs/builtin-macros/ord) | `compare(other: T): number` | Total ordering comparison (-1, 0, 1) |
|
|
15
|
+
| [`PartialOrd`](../docs/builtin-macros/partial-ord) | `partialCompare(other: T): number | null` | Partial ordering comparison |
|
|
16
|
+
| [`Serialize`](../docs/builtin-macros/serialize) | `toJSON(): Record<string, unknown>` | JSON serialization with type handling |
|
|
17
|
+
| [`Deserialize`](../docs/builtin-macros/deserialize) | `static fromJSON(data: unknown): T` | JSON deserialization with validation |
|
|
18
|
+
|
|
19
|
+
## Using Built-in Macros
|
|
20
|
+
|
|
21
|
+
Built-in macros don't require imports. Just use them with `@derive`:
|
|
22
|
+
|
|
23
|
+
TypeScript
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
/** @derive(Debug, Clone, PartialEq) */
|
|
27
|
+
class User {
|
|
28
|
+
name: string;
|
|
29
|
+
age: number;
|
|
30
|
+
|
|
31
|
+
constructor(name: string, age: number) {
|
|
32
|
+
this.name = name;
|
|
33
|
+
this.age = age;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Interface Support
|
|
39
|
+
|
|
40
|
+
All built-in macros work with interfaces. For interfaces, methods are generated as functions in a namespace with the same name, using `self` as the first parameter:
|
|
41
|
+
|
|
42
|
+
TypeScript
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
/** @derive(Debug, Clone, PartialEq) */
|
|
46
|
+
interface Point {
|
|
47
|
+
x: number;
|
|
48
|
+
y: number;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Generated namespace:
|
|
52
|
+
// namespace Point {
|
|
53
|
+
// export function toString(self: Point): string { ... }
|
|
54
|
+
// export function clone(self: Point): Point { ... }
|
|
55
|
+
// export function equals(self: Point, other: Point): boolean { ... }
|
|
56
|
+
// export function hashCode(self: Point): number { ... }
|
|
57
|
+
// }
|
|
58
|
+
|
|
59
|
+
const point: Point = { x: 10, y: 20 };
|
|
60
|
+
|
|
61
|
+
// Use the namespace functions
|
|
62
|
+
console.log(Point.toString(point)); // "Point { x: 10, y: 20 }"
|
|
63
|
+
const copy = Point.clone(point); // { x: 10, y: 20 }
|
|
64
|
+
console.log(Point.equals(point, copy)); // true
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Enum Support
|
|
68
|
+
|
|
69
|
+
All built-in macros work with enums. For enums, methods are generated as functions in a namespace with the same name:
|
|
70
|
+
|
|
71
|
+
TypeScript
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
/** @derive(Debug, Clone, PartialEq, Serialize, Deserialize) */
|
|
75
|
+
enum Status {
|
|
76
|
+
Active = "active",
|
|
77
|
+
Inactive = "inactive",
|
|
78
|
+
Pending = "pending",
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Generated namespace:
|
|
82
|
+
// namespace Status {
|
|
83
|
+
// export function toString(value: Status): string { ... }
|
|
84
|
+
// export function clone(value: Status): Status { ... }
|
|
85
|
+
// export function equals(a: Status, b: Status): boolean { ... }
|
|
86
|
+
// export function hashCode(value: Status): number { ... }
|
|
87
|
+
// export function toJSON(value: Status): string | number { ... }
|
|
88
|
+
// export function fromJSON(data: unknown): Status { ... }
|
|
89
|
+
// }
|
|
90
|
+
|
|
91
|
+
// Use the namespace functions
|
|
92
|
+
console.log(Status.toString(Status.Active)); // "Status.Active"
|
|
93
|
+
console.log(Status.equals(Status.Active, Status.Active)); // true
|
|
94
|
+
const json = Status.toJSON(Status.Pending); // "pending"
|
|
95
|
+
const parsed = Status.fromJSON("active"); // Status.Active
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Type Alias Support
|
|
99
|
+
|
|
100
|
+
All built-in macros work with type aliases. For object type aliases, field-aware methods are generated in a namespace:
|
|
101
|
+
|
|
102
|
+
TypeScript
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
/** @derive(Debug, Clone, PartialEq, Serialize, Deserialize) */
|
|
106
|
+
type Point = {
|
|
107
|
+
x: number;
|
|
108
|
+
y: number;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// Generated namespace:
|
|
112
|
+
// namespace Point {
|
|
113
|
+
// export function toString(value: Point): string { ... }
|
|
114
|
+
// export function clone(value: Point): Point { ... }
|
|
115
|
+
// export function equals(a: Point, b: Point): boolean { ... }
|
|
116
|
+
// export function hashCode(value: Point): number { ... }
|
|
117
|
+
// export function toJSON(value: Point): Record<string, unknown> { ... }
|
|
118
|
+
// export function fromJSON(data: unknown): Point { ... }
|
|
119
|
+
// }
|
|
120
|
+
|
|
121
|
+
const point: Point = { x: 10, y: 20 };
|
|
122
|
+
console.log(Point.toString(point)); // "Point { x: 10, y: 20 }"
|
|
123
|
+
const copy = Point.clone(point); // { x: 10, y: 20 }
|
|
124
|
+
console.log(Point.equals(point, copy)); // true
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Union type aliases also work, using JSON-based implementations:
|
|
128
|
+
|
|
129
|
+
TypeScript
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
/** @derive(Debug, PartialEq) */
|
|
133
|
+
type ApiStatus = "loading" | "success" | "error";
|
|
134
|
+
|
|
135
|
+
const status: ApiStatus = "success";
|
|
136
|
+
console.log(ApiStatus.toString(status)); // "ApiStatus(\\"success\\")"
|
|
137
|
+
console.log(ApiStatus.equals("success", "success")); // true
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Combining Macros
|
|
141
|
+
|
|
142
|
+
All macros can be used together. They don't conflict and each generates independent methods:
|
|
143
|
+
|
|
144
|
+
TypeScript
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
const user = new User("Alice", 30);
|
|
148
|
+
|
|
149
|
+
// Debug
|
|
113
150
|
console.log(user.toString());
|
|
114
|
-
//
|
|
115
|
-
|
|
116
|
-
//
|
|
117
|
-
const
|
|
118
|
-
console.log(copy.name);
|
|
119
|
-
|
|
120
|
-
//
|
|
121
|
-
console.log(user.equals(copy));
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
151
|
+
// "User { name: Alice, age: 30 }"
|
|
152
|
+
|
|
153
|
+
// Clone
|
|
154
|
+
const copy = user.clone();
|
|
155
|
+
console.log(copy.name); // "Alice"
|
|
156
|
+
|
|
157
|
+
// Eq
|
|
158
|
+
console.log(user.equals(copy)); // true
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Detailed Documentation
|
|
162
|
+
|
|
163
|
+
Each macro has its own options and behaviors:
|
|
164
|
+
|
|
165
|
+
* [**Debug**](../docs/builtin-macros/debug) - Customizable field renaming and skipping
|
|
166
|
+
* [**Clone**](../docs/builtin-macros/clone) - Deep copying for all field types
|
|
167
|
+
* [**Default**](../docs/builtin-macros/default) - Default value generation with field attributes
|
|
168
|
+
* [**Hash**](../docs/builtin-macros/hash) - Hash code generation for use in maps and sets
|
|
169
|
+
* [**PartialEq**](../docs/builtin-macros/partial-eq) - Value-based equality comparison
|
|
170
|
+
* [**Ord**](../docs/builtin-macros/ord) - Total ordering for sorting
|
|
171
|
+
* [**PartialOrd**](../docs/builtin-macros/partial-ord) - Partial ordering comparison
|
|
172
|
+
* [**Serialize**](../docs/builtin-macros/serialize) - JSON serialization with serde-style options
|
|
173
|
+
* [**Deserialize**](../docs/builtin-macros/deserialize) - JSON deserialization with validation
|
|
@@ -85,31 +85,6 @@ export function versionCompare(a: Version, b: Version): number {
|
|
|
85
85
|
}
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
-
Generated output:
|
|
89
|
-
|
|
90
|
-
```typescript
|
|
91
|
-
class Version {
|
|
92
|
-
major: number;
|
|
93
|
-
minor: number;
|
|
94
|
-
patch: number;
|
|
95
|
-
|
|
96
|
-
static compareTo(a: Version, b: Version): number {
|
|
97
|
-
return versionCompare(a, b);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export function versionCompare(a: Version, b: Version): number {
|
|
102
|
-
if (a === b) return 0;
|
|
103
|
-
const cmp0 = a.major < b.major ? -1 : a.major > b.major ? 1 : 0;
|
|
104
|
-
if (cmp0 !== 0) return cmp0;
|
|
105
|
-
const cmp1 = a.minor < b.minor ? -1 : a.minor > b.minor ? 1 : 0;
|
|
106
|
-
if (cmp1 !== 0) return cmp1;
|
|
107
|
-
const cmp2 = a.patch < b.patch ? -1 : a.patch > b.patch ? 1 : 0;
|
|
108
|
-
if (cmp2 !== 0) return cmp2;
|
|
109
|
-
return 0;
|
|
110
|
-
}
|
|
111
|
-
```
|
|
112
|
-
|
|
113
88
|
## Ord vs PartialOrd
|
|
114
89
|
|
|
115
90
|
- Use **Ord** when all values are comparable (total ordering)
|
|
@@ -90,48 +90,6 @@ export function userHashCode(value: User): number {
|
|
|
90
90
|
}
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
Generated output:
|
|
94
|
-
|
|
95
|
-
```typescript
|
|
96
|
-
class User {
|
|
97
|
-
id: number;
|
|
98
|
-
name: string;
|
|
99
|
-
|
|
100
|
-
cachedScore: number;
|
|
101
|
-
|
|
102
|
-
static equals(a: User, b: User): boolean {
|
|
103
|
-
return userEquals(a, b);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
static hashCode(value: User): number {
|
|
107
|
-
return userHashCode(value);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export function userEquals(a: User, b: User): boolean {
|
|
112
|
-
if (a === b) return true;
|
|
113
|
-
return a.id === b.id && a.name === b.name;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export function userHashCode(value: User): number {
|
|
117
|
-
let hash = 17;
|
|
118
|
-
hash =
|
|
119
|
-
(hash * 31 +
|
|
120
|
-
(Number.isInteger(value.id)
|
|
121
|
-
? value.id | 0
|
|
122
|
-
: value.id
|
|
123
|
-
.toString()
|
|
124
|
-
.split('')
|
|
125
|
-
.reduce((h, c) => (h * 31 + c.charCodeAt(0)) | 0, 0))) |
|
|
126
|
-
0;
|
|
127
|
-
hash =
|
|
128
|
-
(hash * 31 +
|
|
129
|
-
(value.name ?? '').split('').reduce((h, c) => (h * 31 + c.charCodeAt(0)) | 0, 0)) |
|
|
130
|
-
0;
|
|
131
|
-
return hash;
|
|
132
|
-
}
|
|
133
|
-
```
|
|
134
|
-
|
|
135
93
|
## Equality Contract
|
|
136
94
|
|
|
137
95
|
When implementing `PartialEq`, consider also implementing `Hash`:
|
|
@@ -192,45 +150,3 @@ export function userHashCode(value: User): number {
|
|
|
192
150
|
return hash;
|
|
193
151
|
}
|
|
194
152
|
```
|
|
195
|
-
|
|
196
|
-
Generated output:
|
|
197
|
-
|
|
198
|
-
```typescript
|
|
199
|
-
class User {
|
|
200
|
-
id: number;
|
|
201
|
-
name: string;
|
|
202
|
-
|
|
203
|
-
cachedScore: number;
|
|
204
|
-
|
|
205
|
-
static equals(a: User, b: User): boolean {
|
|
206
|
-
return userEquals(a, b);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
static hashCode(value: User): number {
|
|
210
|
-
return userHashCode(value);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
export function userEquals(a: User, b: User): boolean {
|
|
215
|
-
if (a === b) return true;
|
|
216
|
-
return a.id === b.id && a.name === b.name;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
export function userHashCode(value: User): number {
|
|
220
|
-
let hash = 17;
|
|
221
|
-
hash =
|
|
222
|
-
(hash * 31 +
|
|
223
|
-
(Number.isInteger(value.id)
|
|
224
|
-
? value.id | 0
|
|
225
|
-
: value.id
|
|
226
|
-
.toString()
|
|
227
|
-
.split('')
|
|
228
|
-
.reduce((h, c) => (h * 31 + c.charCodeAt(0)) | 0, 0))) |
|
|
229
|
-
0;
|
|
230
|
-
hash =
|
|
231
|
-
(hash * 31 +
|
|
232
|
-
(value.name ?? '').split('').reduce((h, c) => (h * 31 + c.charCodeAt(0)) | 0, 0)) |
|
|
233
|
-
0;
|
|
234
|
-
return hash;
|
|
235
|
-
}
|
|
236
|
-
```
|