@alloy-js/csharp 0.21.0-dev.16 → 0.21.0-dev.17
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/dist/src/create-library.d.ts.map +1 -1
- package/dist/src/create-library.js +45 -37
- package/dist/src/create-library.js.map +1 -1
- package/dist/src/create-library.test.js +26 -0
- package/dist/src/create-library.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/create-library.test.tsx +20 -0
- package/src/create-library.ts +72 -46
package/package.json
CHANGED
|
@@ -191,3 +191,23 @@ it("has built-ins available", () => {
|
|
|
191
191
|
var directoryName = info.DirectoryName?.Length;
|
|
192
192
|
`);
|
|
193
193
|
});
|
|
194
|
+
|
|
195
|
+
it("can render multiple times", () => {
|
|
196
|
+
const System = createLibrary("System", {
|
|
197
|
+
String: {
|
|
198
|
+
kind: "class",
|
|
199
|
+
members: {},
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
expect(<TestNamespace>{System.String}</TestNamespace>).toRenderTo(`
|
|
203
|
+
using System;
|
|
204
|
+
|
|
205
|
+
String
|
|
206
|
+
`);
|
|
207
|
+
|
|
208
|
+
expect(<TestNamespace>{System.String}</TestNamespace>).toRenderTo(`
|
|
209
|
+
using System;
|
|
210
|
+
|
|
211
|
+
String
|
|
212
|
+
`);
|
|
213
|
+
});
|
package/src/create-library.ts
CHANGED
|
@@ -96,16 +96,15 @@ export type LibraryFrom<T> = {
|
|
|
96
96
|
} & LibrarySymbolReference;
|
|
97
97
|
|
|
98
98
|
interface InternalContext {
|
|
99
|
-
binder
|
|
100
|
-
ownerSymbol(): NamedTypeSymbol;
|
|
99
|
+
ownerSymbol(binder: Binder | undefined): NamedTypeSymbol;
|
|
101
100
|
}
|
|
102
101
|
|
|
103
102
|
export function createLibrary<T extends Record<string, Descriptor>>(
|
|
104
103
|
rootNs: string,
|
|
105
104
|
props: T,
|
|
106
105
|
): LibraryFrom<T> {
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
const ownerSymbolPerBinder = new WeakMap<Binder, NamespaceSymbol>();
|
|
107
|
+
|
|
109
108
|
const namespaceNames = rootNs.split(".");
|
|
110
109
|
|
|
111
110
|
return createSymbolEntry(
|
|
@@ -115,33 +114,24 @@ export function createLibrary<T extends Record<string, Descriptor>>(
|
|
|
115
114
|
members: props,
|
|
116
115
|
},
|
|
117
116
|
{
|
|
118
|
-
binder
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
if (ownerSymbol!.members.symbolNames.has(name)) {
|
|
133
|
-
ownerSymbol = ownerSymbol!.members.symbolNames.get(
|
|
134
|
-
name,
|
|
135
|
-
)! as NamespaceSymbol;
|
|
136
|
-
} else {
|
|
137
|
-
ownerSymbol = new NamespaceSymbol(name, ownerSymbol!, {
|
|
138
|
-
binder,
|
|
139
|
-
refkeys: refkey(),
|
|
140
|
-
});
|
|
117
|
+
ownerSymbol(binder: Binder | undefined) {
|
|
118
|
+
return mapGet(ownerSymbolPerBinder, binder, () => {
|
|
119
|
+
let ownerSymbol = getGlobalNamespace(binder);
|
|
120
|
+
for (const name of namespaceNames.slice(0, -1)) {
|
|
121
|
+
if (ownerSymbol!.members.symbolNames.has(name)) {
|
|
122
|
+
ownerSymbol = ownerSymbol!.members.symbolNames.get(
|
|
123
|
+
name,
|
|
124
|
+
)! as NamespaceSymbol;
|
|
125
|
+
} else {
|
|
126
|
+
ownerSymbol = new NamespaceSymbol(name, ownerSymbol!, {
|
|
127
|
+
binder,
|
|
128
|
+
refkeys: refkey(),
|
|
129
|
+
});
|
|
130
|
+
}
|
|
141
131
|
}
|
|
142
|
-
}
|
|
143
132
|
|
|
144
|
-
|
|
133
|
+
return ownerSymbol;
|
|
134
|
+
});
|
|
145
135
|
},
|
|
146
136
|
},
|
|
147
137
|
) as LibraryFrom<T>;
|
|
@@ -152,24 +142,26 @@ function createSymbolEntry(
|
|
|
152
142
|
descriptor: Descriptor,
|
|
153
143
|
context: InternalContext,
|
|
154
144
|
): LibrarySymbolReference {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
function getSymbol() {
|
|
158
|
-
if (symbol) return symbol;
|
|
145
|
+
const symbols = new WeakMap<Binder, CSharpSymbol>();
|
|
159
146
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
147
|
+
function getSymbol(binder: Binder | undefined) {
|
|
148
|
+
// We cache symbols per binder to ensure we only create one symbol. We also
|
|
149
|
+
// track an unbound symbol for cases where there is no binder (mostly
|
|
150
|
+
// tests).
|
|
151
|
+
return mapGet(symbols, binder, () =>
|
|
152
|
+
createSymbolFromDescriptor(
|
|
153
|
+
name,
|
|
154
|
+
binder,
|
|
155
|
+
descriptor,
|
|
156
|
+
context,
|
|
157
|
+
initializeMembers,
|
|
158
|
+
),
|
|
165
159
|
);
|
|
166
|
-
return symbol;
|
|
167
160
|
}
|
|
168
161
|
|
|
169
162
|
const newContext: InternalContext = {
|
|
170
|
-
binder
|
|
171
|
-
|
|
172
|
-
return getSymbol() as NamedTypeSymbol;
|
|
163
|
+
ownerSymbol(binder) {
|
|
164
|
+
return getSymbol(binder) as NamedTypeSymbol;
|
|
173
165
|
},
|
|
174
166
|
};
|
|
175
167
|
|
|
@@ -182,10 +174,10 @@ function createSymbolEntry(
|
|
|
182
174
|
|
|
183
175
|
const obj: LibrarySymbolReference & Record<string, unknown> = {
|
|
184
176
|
[REFKEYABLE]() {
|
|
185
|
-
return getSymbol().refkeys[0];
|
|
177
|
+
return getSymbol(useBinder()).refkeys[0];
|
|
186
178
|
},
|
|
187
179
|
[TO_SYMBOL]() {
|
|
188
|
-
return getSymbol();
|
|
180
|
+
return getSymbol(useBinder());
|
|
189
181
|
},
|
|
190
182
|
};
|
|
191
183
|
|
|
@@ -209,12 +201,12 @@ function createSymbolEntry(
|
|
|
209
201
|
|
|
210
202
|
function createSymbolFromDescriptor(
|
|
211
203
|
name: string,
|
|
204
|
+
binder: Binder | undefined,
|
|
212
205
|
descriptor: Descriptor,
|
|
213
206
|
context: InternalContext,
|
|
214
207
|
lazyMemberInitializer: () => void,
|
|
215
208
|
): CSharpSymbol {
|
|
216
|
-
const ownerSymbol = context.ownerSymbol();
|
|
217
|
-
const binder = context.binder();
|
|
209
|
+
const ownerSymbol = context.ownerSymbol(binder);
|
|
218
210
|
|
|
219
211
|
switch (descriptor.kind) {
|
|
220
212
|
case "namespace":
|
|
@@ -268,3 +260,37 @@ function createSymbolFromDescriptor(
|
|
|
268
260
|
throw "Unsupported";
|
|
269
261
|
}
|
|
270
262
|
}
|
|
263
|
+
|
|
264
|
+
const defaultsPerMap = new WeakMap<object, unknown>();
|
|
265
|
+
|
|
266
|
+
function mapGet<T extends WeakKey, V>(
|
|
267
|
+
map: WeakMap<T, V>,
|
|
268
|
+
key: T | undefined,
|
|
269
|
+
): V | undefined;
|
|
270
|
+
function mapGet<T extends WeakKey, V>(
|
|
271
|
+
map: WeakMap<T, V>,
|
|
272
|
+
key: T | undefined,
|
|
273
|
+
init: () => V,
|
|
274
|
+
): V;
|
|
275
|
+
function mapGet<T extends WeakKey, V>(
|
|
276
|
+
map: WeakMap<T, V>,
|
|
277
|
+
key: T | undefined,
|
|
278
|
+
init?: () => V,
|
|
279
|
+
): V | undefined {
|
|
280
|
+
if (key === undefined) {
|
|
281
|
+
// Use a per-map default store when callers request a value for an undefined key.
|
|
282
|
+
let value = defaultsPerMap.get(map as unknown as object) as V | undefined;
|
|
283
|
+
if (value === undefined && init) {
|
|
284
|
+
value = init();
|
|
285
|
+
defaultsPerMap.set(map as unknown as object, value);
|
|
286
|
+
}
|
|
287
|
+
return value;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
let value = map.get(key);
|
|
291
|
+
if (value === undefined && init) {
|
|
292
|
+
value = init();
|
|
293
|
+
map.set(key, value);
|
|
294
|
+
}
|
|
295
|
+
return value;
|
|
296
|
+
}
|