@alloy-js/core 0.20.0-dev.3 → 0.20.0-dev.6

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.
Files changed (137) hide show
  1. package/dist/src/binder.d.ts +62 -38
  2. package/dist/src/binder.d.ts.map +1 -1
  3. package/dist/src/binder.js +214 -173
  4. package/dist/src/components/Declaration.d.ts +2 -2
  5. package/dist/src/components/Declaration.d.ts.map +1 -1
  6. package/dist/src/components/Declaration.js +8 -2
  7. package/dist/src/components/MemberDeclaration.d.ts +2 -2
  8. package/dist/src/components/MemberDeclaration.d.ts.map +1 -1
  9. package/dist/src/components/MemberDeclaration.js +9 -5
  10. package/dist/src/components/MemberScope.d.ts +30 -13
  11. package/dist/src/components/MemberScope.d.ts.map +1 -1
  12. package/dist/src/components/MemberScope.js +37 -15
  13. package/dist/src/components/Output.d.ts.map +1 -1
  14. package/dist/src/components/Output.js +2 -5
  15. package/dist/src/components/ReferenceOrContent.d.ts +1 -1
  16. package/dist/src/components/ReferenceOrContent.d.ts.map +1 -1
  17. package/dist/src/components/Scope.d.ts +5 -5
  18. package/dist/src/components/Scope.d.ts.map +1 -1
  19. package/dist/src/components/Scope.js +9 -5
  20. package/dist/src/context/member-scope.d.ts +7 -8
  21. package/dist/src/context/member-scope.d.ts.map +1 -1
  22. package/dist/src/context/member-scope.js +5 -5
  23. package/dist/src/context/name-policy.d.ts.map +1 -1
  24. package/dist/src/context/name-policy.js +3 -0
  25. package/dist/src/context/scope.d.ts +1 -0
  26. package/dist/src/context/scope.d.ts.map +1 -1
  27. package/dist/src/context/scope.js +7 -0
  28. package/dist/src/inspect.browser.d.ts +5 -0
  29. package/dist/src/inspect.browser.d.ts.map +1 -0
  30. package/dist/src/inspect.browser.js +5 -0
  31. package/dist/src/inspect.d.ts +2 -0
  32. package/dist/src/inspect.d.ts.map +1 -0
  33. package/dist/src/inspect.js +1 -0
  34. package/dist/src/name-policy.d.ts +11 -0
  35. package/dist/src/name-policy.d.ts.map +1 -1
  36. package/dist/src/name-policy.js +3 -0
  37. package/dist/src/reactive-union-set.d.ts.map +1 -1
  38. package/dist/src/reactive-union-set.js +12 -8
  39. package/dist/src/refkey.d.ts +39 -3
  40. package/dist/src/refkey.d.ts.map +1 -1
  41. package/dist/src/refkey.js +52 -8
  42. package/dist/src/symbols/basic-scope.d.ts +14 -0
  43. package/dist/src/symbols/basic-scope.d.ts.map +1 -0
  44. package/dist/src/symbols/basic-scope.js +20 -0
  45. package/dist/src/symbols/basic-symbol.d.ts +19 -0
  46. package/dist/src/symbols/basic-symbol.d.ts.map +1 -0
  47. package/dist/src/symbols/basic-symbol.js +28 -0
  48. package/dist/src/symbols/index.d.ts +3 -1
  49. package/dist/src/symbols/index.d.ts.map +1 -1
  50. package/dist/src/symbols/index.js +3 -1
  51. package/dist/src/symbols/output-scope.d.ts +70 -41
  52. package/dist/src/symbols/output-scope.d.ts.map +1 -1
  53. package/dist/src/symbols/output-scope.js +98 -130
  54. package/dist/src/symbols/output-space.d.ts +25 -0
  55. package/dist/src/symbols/output-space.d.ts.map +1 -0
  56. package/dist/src/symbols/output-space.js +35 -0
  57. package/dist/src/symbols/output-symbol.d.ts +213 -37
  58. package/dist/src/symbols/output-symbol.d.ts.map +1 -1
  59. package/dist/src/symbols/output-symbol.js +323 -203
  60. package/dist/src/symbols/symbol-flow.d.ts +1 -1
  61. package/dist/src/symbols/symbol-flow.d.ts.map +1 -1
  62. package/dist/src/symbols/symbol-flow.js +22 -7
  63. package/dist/src/symbols/symbol-slot.d.ts +27 -9
  64. package/dist/src/symbols/symbol-slot.d.ts.map +1 -1
  65. package/dist/src/symbols/symbol-slot.js +20 -4
  66. package/dist/src/symbols/symbol-table.d.ts +19 -8
  67. package/dist/src/symbols/symbol-table.d.ts.map +1 -1
  68. package/dist/src/symbols/symbol-table.js +65 -16
  69. package/dist/src/tracer.d.ts +15 -3
  70. package/dist/src/tracer.d.ts.map +1 -1
  71. package/dist/src/tracer.js +39 -63
  72. package/dist/src/utils.d.ts +1 -1
  73. package/dist/src/utils.d.ts.map +1 -1
  74. package/dist/src/utils.js +4 -4
  75. package/dist/src/write-output.d.ts +1 -1
  76. package/dist/src/write-output.d.ts.map +1 -1
  77. package/dist/src/write-output.js +31 -37
  78. package/dist/test/components/declaration.test.js +9 -14
  79. package/dist/test/components/reference-or-content.test.js +2 -2
  80. package/dist/test/symbols/output-scope.test.js +33 -198
  81. package/dist/test/symbols/output-symbol.test.js +139 -385
  82. package/dist/test/symbols/resolution.test.js +431 -114
  83. package/dist/test/symbols/symbol-table.test.d.ts +2 -0
  84. package/dist/test/symbols/symbol-table.test.d.ts.map +1 -0
  85. package/dist/test/symbols/symbol-table.test.js +14 -0
  86. package/dist/test/symbols/utils.d.ts +10 -24
  87. package/dist/test/symbols/utils.d.ts.map +1 -1
  88. package/dist/test/symbols/utils.js +23 -45
  89. package/dist/tsconfig.tsbuildinfo +1 -1
  90. package/package.json +4 -2
  91. package/src/binder.ts +348 -273
  92. package/src/components/Declaration.tsx +13 -3
  93. package/src/components/MemberDeclaration.tsx +15 -8
  94. package/src/components/MemberScope.tsx +61 -20
  95. package/src/components/Output.tsx +0 -4
  96. package/src/components/Scope.tsx +16 -9
  97. package/src/context/member-scope.ts +10 -10
  98. package/src/context/name-policy.ts +3 -0
  99. package/src/context/scope.ts +9 -0
  100. package/src/inspect.browser.ts +6 -0
  101. package/src/inspect.ts +1 -0
  102. package/src/name-policy.ts +14 -0
  103. package/src/reactive-union-set.ts +14 -8
  104. package/src/refkey.ts +88 -14
  105. package/src/symbols/basic-scope.ts +23 -0
  106. package/src/symbols/basic-symbol.ts +32 -0
  107. package/src/symbols/index.ts +3 -1
  108. package/src/symbols/output-scope.ts +131 -170
  109. package/src/symbols/output-space.ts +49 -0
  110. package/src/symbols/output-symbol.ts +434 -258
  111. package/src/symbols/symbol-flow.ts +38 -9
  112. package/src/symbols/symbol-slot.tsx +46 -8
  113. package/src/symbols/symbol-table.ts +95 -21
  114. package/src/tracer.ts +53 -83
  115. package/src/utils.tsx +4 -4
  116. package/src/write-output.ts +33 -45
  117. package/temp/api.json +5551 -3066
  118. package/test/components/declaration.test.tsx +6 -19
  119. package/test/components/reference-or-content.test.tsx +2 -2
  120. package/test/symbols/output-scope.test.ts +33 -125
  121. package/test/symbols/output-symbol.test.ts +128 -348
  122. package/test/symbols/resolution.test.ts +530 -117
  123. package/test/symbols/symbol-table.test.ts +15 -0
  124. package/test/symbols/utils.ts +38 -74
  125. package/tsdoc.json +4 -0
  126. package/dist/src/slot.d.ts +0 -15
  127. package/dist/src/slot.d.ts.map +0 -1
  128. package/dist/src/slot.js +0 -50
  129. package/dist/src/symbols/flags.d.ts +0 -70
  130. package/dist/src/symbols/flags.d.ts.map +0 -1
  131. package/dist/src/symbols/flags.js +0 -72
  132. package/dist/test/components/slot.test.d.ts +0 -2
  133. package/dist/test/components/slot.test.d.ts.map +0 -1
  134. package/dist/test/components/slot.test.js +0 -134
  135. package/src/slot.ts +0 -89
  136. package/src/symbols/flags.ts +0 -82
  137. package/test/components/slot.test.tsx +0 -174
@@ -1,4 +1,5 @@
1
1
  import {
2
+ effect,
2
3
  reactive,
3
4
  ReactiveFlags,
4
5
  shallowReactive,
@@ -6,33 +7,35 @@ import {
6
7
  TrackOpTypes,
7
8
  trigger,
8
9
  TriggerOpTypes,
9
- watch,
10
10
  } from "@vue/reactivity";
11
11
  import type { Binder } from "../binder.js";
12
12
  import { useBinder } from "../context/binder.js";
13
- import { useScope } from "../context/scope.js";
14
- import type { ReactiveUnionSetOptions } from "../reactive-union-set.js";
15
- import type { Refkey } from "../refkey.js";
16
- import {
17
- formatScope,
18
- formatScopeName,
19
- trace,
20
- traceEffect,
21
- TracePhase,
22
- } from "../tracer.js";
23
- import { OutputScopeFlags } from "./flags.js";
24
- import type { OutputSymbol } from "./output-symbol.js";
25
- import { SymbolTable } from "./symbol-table.js";
13
+ import { inspect } from "../inspect.js";
14
+ import { untrack } from "../reactivity.js";
15
+ import { formatScope, trace, traceEffect, TracePhase } from "../tracer.js";
16
+ import { OutputDeclarationSpace, OutputSpace } from "./output-space.js";
17
+ import { OutputSymbol } from "./output-symbol.js";
26
18
 
27
19
  let scopeCount = 0;
28
20
 
29
21
  export interface OutputScopeOptions {
30
- flags?: OutputScopeFlags;
31
- kind?: string;
22
+ /**
23
+ * Arbitrary metadata that is associated with this scope.
24
+ */
32
25
  metadata?: Record<string, unknown>;
33
- parent?: OutputScope;
34
- owner?: OutputSymbol;
26
+
27
+ /**
28
+ * The binder instance this scope belongs to. If not provided, it will
29
+ * attempt to find the current binder from context.
30
+ */
35
31
  binder?: Binder;
32
+
33
+ /**
34
+ * The owner symbol of this scope. When provided, this scope becomes a member
35
+ * scope, which exposes the symbols on its owner symbol instead of having its
36
+ * own declaration spaces.
37
+ */
38
+ ownerSymbol?: OutputSymbol;
36
39
  }
37
40
 
38
41
  /**
@@ -53,16 +56,20 @@ export interface OutputScopeOptions {
53
56
  * Scopes are reactive values, which allows you to observe changes to the scope
54
57
  * within a reactive context.
55
58
  */
56
- export class OutputScope {
57
- // my kingdom for decorators
59
+ export abstract class OutputScope {
60
+ static readonly declarationSpaces: Readonly<string[]> = [] as const;
61
+
58
62
  #name: string;
59
63
  /**
60
64
  * The name of the scope.
65
+ *
66
+ * @reactive
61
67
  */
62
68
  get name() {
63
69
  track(this, TrackOpTypes.GET, "name");
64
70
  return this.#name;
65
71
  }
72
+
66
73
  set name(name: string) {
67
74
  const old = this.#name;
68
75
  this.#name = name;
@@ -72,85 +79,66 @@ export class OutputScope {
72
79
  #id: number;
73
80
  /**
74
81
  * The unique id of this scope.
82
+ *
83
+ * @readonly
75
84
  */
76
85
  get id() {
77
86
  return this.#id;
78
87
  }
79
88
 
80
- #kind: string;
81
-
82
- /**
83
- * The kind of scope. Subtypes will likely provide a set of known scope kinds.
84
- * The kind is not used by the binder itself.
85
- */
86
- get kind() {
87
- return this.#kind;
88
- }
89
-
90
- #flags: OutputScopeFlags;
91
- /**
92
- * The flags that describe this scope.
93
- */
94
- get flags() {
95
- track(this, TrackOpTypes.GET, "flags");
96
- return this.#flags;
97
- }
98
- set flags(flags: OutputScopeFlags) {
99
- const old = this.#flags;
100
- this.#flags = flags;
101
- trigger(this, TriggerOpTypes.SET, "flags", flags, old);
102
- }
103
-
104
89
  // read only
105
90
  #metadata: Record<string, unknown>;
91
+ /**
92
+ * Arbitrary metadata associated with this scope. This property is not
93
+ * reactive but the metadata object is a reactive object.
94
+ *
95
+ * @readonly
96
+ */
106
97
  get metadata() {
107
98
  return this.#metadata;
108
99
  }
109
100
 
110
101
  #parent?: OutputScope;
102
+
111
103
  /**
112
- * The container of this scope. This is only defined for scopes which don't
113
- * have the {@link OutputScopeFlags.StaticMemberScope} or
114
- * {@link OutputScopeFlags.InstanceMemberScope} flag.
104
+ * The parent scope of this scope. Undefined if this is a root scope.
105
+ *
106
+ * @reactive
115
107
  */
116
108
  get parent() {
109
+ track(this, TrackOpTypes.GET, "parent");
117
110
  return this.#parent;
118
111
  }
119
112
 
120
- #owner?: OutputSymbol;
121
- /**
122
- * The symbol that owns this scope. This is only defined for scopes that have
123
- * the {@link OutputScopeFlags.StaticMemberScope} or
124
- * {@link OutputScopeFlags.InstanceMemberScope} flag.
125
- */
126
- get owner() {
127
- return this.#owner;
128
- }
113
+ set parent(scope: OutputScope | undefined) {
114
+ const old = this.#parent;
129
115
 
130
- #symbols: SymbolTable;
131
- /**
132
- * The symbols defined within this scope.
133
- */
134
- get symbols() {
135
- return this.#symbols;
116
+ if (old) {
117
+ old.children.delete(this);
118
+ }
119
+
120
+ if (scope) {
121
+ scope.children.add(this);
122
+ }
123
+
124
+ trigger(this, TriggerOpTypes.SET, "parent", scope, old);
125
+ this.#parent = scope;
136
126
  }
137
127
 
138
- #symbolsByRefkey: ReadonlyMap<Refkey, OutputSymbol>;
128
+ #spaces: Record<string, OutputDeclarationSpace>;
129
+
139
130
  /**
140
- * The symbols defined within this scope, indexed by refkey.
131
+ * Get the declaration space for the given key.
141
132
  */
142
- get symbolsByRefkey() {
143
- return this.#symbolsByRefkey;
144
- }
145
-
146
- #symbolNames: ReadonlySet<string>;
147
- get symbolNames() {
148
- return this.#symbolNames;
133
+ spaceFor(key: string): OutputSpace | undefined {
134
+ return this.#spaces[key];
149
135
  }
150
136
 
151
137
  #children: Set<OutputScope>;
152
138
  /**
153
139
  * The scopes nested within this scope.
140
+ *
141
+ * @readonly
154
142
  */
155
143
  get children() {
156
144
  return this.#children;
@@ -159,6 +147,8 @@ export class OutputScope {
159
147
  #binder: Binder | undefined;
160
148
  /**
161
149
  * The binder that created this scope.
150
+ *
151
+ * @readonly
162
152
  */
163
153
  get binder() {
164
154
  return this.#binder;
@@ -166,43 +156,34 @@ export class OutputScope {
166
156
 
167
157
  [ReactiveFlags.SKIP] = this;
168
158
 
169
- constructor(name: string, options: OutputScopeOptions = {}) {
159
+ constructor(
160
+ name: string,
161
+ parentScope: OutputScope | undefined,
162
+ options: OutputScopeOptions = {},
163
+ ) {
170
164
  this.#name = name;
171
165
  this.#id = scopeCount++;
172
- this.#flags = options.flags ?? OutputScopeFlags.None;
173
- this.#kind = options.kind ?? "scope";
174
166
  this.#metadata = reactive(options.metadata ?? {});
175
167
  this.#binder = options.binder ?? useBinder();
176
- this.#owner = options.owner;
177
168
  this.#children = shallowReactive(new Set());
178
-
179
- if (this.#flags & OutputScopeFlags.MemberScope) {
180
- if (!this.#owner) {
181
- throw new Error("Member scopes must have an owner");
182
- }
183
- } else {
184
- if (!this.#parent) {
185
- this.#parent =
186
- options.parent ?? useScope() ?? this.#binder?.globalScope;
187
- }
188
- if (this.#parent) {
189
- // not global scope
190
- this.#parent.children.add(this);
191
- }
192
- }
193
-
194
- this.#symbols = new SymbolTable(this, {
195
- nameConflictResolver: this.#binder?.nameConflictResolver,
196
- });
197
- this.#symbolsByRefkey = this.#symbols.createIndex((s) => s.refkeys);
198
- this.#symbolNames = this.#symbols.createDerivedSet((s) => {
199
- return s.name;
169
+ this.#parent = parentScope;
170
+ effect(() => {
171
+ this.#setOwnerSymbol(options.ownerSymbol?.movedTo ?? options.ownerSymbol);
200
172
  });
201
173
 
202
174
  if (this.#parent) {
203
175
  this.#parent.children.add(this);
204
176
  }
205
177
 
178
+ const constructor = this.constructor as typeof OutputScope;
179
+
180
+ this.#spaces = Object.fromEntries(
181
+ constructor.declarationSpaces.map((spaceKey) => [
182
+ spaceKey,
183
+ new OutputDeclarationSpace(this, spaceKey, this.#binder),
184
+ ]),
185
+ );
186
+
206
187
  this.#binder?.notifyScopeCreated(this);
207
188
 
208
189
  trace(TracePhase.scope.create, () => `${formatScope(this)}`);
@@ -211,86 +192,66 @@ export class OutputScope {
211
192
  });
212
193
  }
213
194
 
214
- moveSymbolsFrom(
215
- source: OutputScope,
216
- options?: ReactiveUnionSetOptions<OutputSymbol>,
217
- ) {
218
- trace(
219
- TracePhase.scope.copySymbols,
220
- () =>
221
- `Moving symbols from ${formatScopeName(source)} to ${formatScopeName(this)}`,
222
- );
223
- this.#symbols.addSubset(source.#symbols, {
224
- onAdd: (symbol) => {
225
- if (options?.onAdd) {
226
- return options.onAdd(symbol);
227
- }
228
- symbol.scope = this;
229
- return symbol;
230
- },
231
- onDelete: (symbol) => {
232
- if (options?.onDelete) {
233
- options.onDelete(symbol);
234
- }
235
- },
236
- });
195
+ /**
196
+ * Get all the declaration spaces in this scope.
197
+ *
198
+ * @readonly
199
+ */
200
+ get spaces() {
201
+ return Object.values(this.#spaces);
237
202
  }
238
203
 
239
- copySymbolsFrom(
240
- source: OutputScope,
241
- options?: ReactiveUnionSetOptions<OutputSymbol>,
242
- ) {
243
- trace(
244
- TracePhase.scope.copySymbols,
245
- () =>
246
- `Copying symbols from ${formatScopeName(source)} to ${formatScopeName(this)}`,
247
- );
248
- this.#symbols.addSubset(source.#symbols, {
249
- onAdd: (symbol) => {
250
- if (options?.onAdd) {
251
- return options.onAdd(symbol);
252
- }
253
- return symbol.copyToScope(this);
254
- },
255
- onDelete: (symbol) => {
256
- if (options?.onDelete) {
257
- options.onDelete(symbol);
258
- }
259
- },
260
- });
204
+ #ownerSymbol: OutputSymbol | undefined;
205
+ /**
206
+ * The symbol whose members are in scope. When an owner symbol is present,
207
+ * this scope is considered a member scope, and does not provide its own
208
+ * declaration spaces.
209
+ *
210
+ * @readonly
211
+ * @reactive
212
+ */
213
+ get ownerSymbol() {
214
+ track(this, TrackOpTypes.GET, "ownerSymbol");
215
+ return this.#ownerSymbol;
261
216
  }
262
217
 
263
- clone(options: { parent?: OutputScope; owner?: OutputSymbol } = {}) {
264
- if (this.#flags & OutputScopeFlags.MemberScope && !options.owner) {
265
- throw new Error("Member scope clones must specify an owner symbol");
266
- } else if (this.#flags & ~OutputScopeFlags.MemberScope && !options.parent) {
267
- throw new Error("Non-member scope clones must specify a parent scope");
268
- }
269
- const clone = new OutputScope(this.#name, {
270
- binder: this.#binder,
271
- flags: this.#flags,
272
- kind: this.#kind,
273
- metadata: this.#metadata,
274
- parent: options.parent,
275
- owner: options.owner,
276
- });
218
+ #setOwnerSymbol(value: OutputSymbol | undefined) {
219
+ const old = this.#ownerSymbol;
220
+ this.#ownerSymbol = value;
221
+ trigger(this, TriggerOpTypes.SET, "ownerSymbol", value, old);
222
+ }
277
223
 
278
- watch(
279
- () => this.name,
280
- (newName) => (clone.name = newName),
281
- );
282
- watch(
283
- () => this.flags,
284
- (newFlags) => (clone.flags = newFlags),
285
- );
286
- // todo: this should be reactive, but cloning non-member scopes
287
- // seems like a very rare thing.
288
- for (const child of this.#children) {
289
- clone.children.add(child.clone());
224
+ /**
225
+ * Whether this scope is a transient scope. Transient scopes are used for
226
+ * temporary values that are to be combined with other non-transient symbols.
227
+ * Scopes are transient when their owner symbol is transient.
228
+ *
229
+ * @readonly
230
+ */
231
+ get isTransient() {
232
+ if (!this.ownerSymbol) {
233
+ return false;
290
234
  }
291
235
 
292
- clone.copySymbolsFrom(this);
236
+ return this.ownerSymbol.isTransient;
237
+ }
238
+ /**
239
+ * Check if this is scope is a member scope. Member scopes have no member
240
+ * spaces of their own, but instead put members of their owner symbol in
241
+ * scope.
242
+ *
243
+ * @readonly
244
+ * @reactive
245
+ */
246
+ get isMemberScope() {
247
+ return !!this.ownerSymbol;
248
+ }
293
249
 
294
- return clone;
250
+ [inspect.custom]() {
251
+ const ownerSymbol =
252
+ this.ownerSymbol ? ` for ${inspect(this.ownerSymbol)}` : "";
253
+ return untrack(
254
+ () => `${this.constructor.name} ${this.name}[${this.id}]${ownerSymbol}`,
255
+ );
295
256
  }
296
257
  }
@@ -0,0 +1,49 @@
1
+ import { Binder } from "../binder.js";
2
+ import { inspect } from "../inspect.js";
3
+ import { untrack } from "../reactivity.js";
4
+ import { OutputScope } from "./output-scope.js";
5
+ import { OutputSymbol } from "./output-symbol.js";
6
+ import { SymbolTable } from "./symbol-table.js";
7
+
8
+ export type OutputSpace = OutputDeclarationSpace | OutputMemberSpace;
9
+ export class OutputDeclarationSpace extends SymbolTable {
10
+ constructor(scope: OutputScope, key: string, binder?: Binder) {
11
+ super(key, binder);
12
+ this.#scope = scope;
13
+ }
14
+
15
+ #scope: OutputScope;
16
+ /**
17
+ * The scope this declaration space belongs to.
18
+ */
19
+ get scope() {
20
+ return this.#scope;
21
+ }
22
+
23
+ [inspect.custom]() {
24
+ return untrack(
25
+ () => `OutputDeclarationSpace for scope ${inspect(this.#scope)}`,
26
+ );
27
+ }
28
+ }
29
+
30
+ export class OutputMemberSpace extends SymbolTable {
31
+ constructor(symbol: OutputSymbol, key: string, binder?: Binder) {
32
+ super(key, binder);
33
+ this.#symbol = symbol;
34
+ }
35
+
36
+ #symbol: OutputSymbol;
37
+ /**
38
+ * The symbol this member space belongs to.
39
+ */
40
+ get symbol() {
41
+ return this.#symbol;
42
+ }
43
+
44
+ [inspect.custom]() {
45
+ return untrack(
46
+ () => `OutputMemberSpace for symbol ${inspect(this.#symbol)}`,
47
+ );
48
+ }
49
+ }