@tsonic/cli 0.0.72 → 0.0.74
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/.tsbuildinfo +1 -1
- package/dist/commands/build-library-bindings-aliases.test.js +63 -7
- package/dist/commands/build-library-bindings-aliases.test.js.map +1 -1
- package/dist/commands/library-bindings-augment.d.ts.map +1 -1
- package/dist/commands/library-bindings-augment.js +0 -3
- package/dist/commands/library-bindings-augment.js.map +1 -1
- package/dist/commands/library-bindings-augment.test.js +46 -0
- package/dist/commands/library-bindings-augment.test.js.map +1 -1
- package/dist/commands/library-bindings-firstparty-regressions.test.js +2425 -0
- package/dist/commands/library-bindings-firstparty-regressions.test.js.map +1 -1
- package/dist/commands/library-bindings-firstparty.d.ts.map +1 -1
- package/dist/commands/library-bindings-firstparty.js +1608 -311
- package/dist/commands/library-bindings-firstparty.js.map +1 -1
- package/dist/surface/profiles.d.ts.map +1 -1
- package/dist/surface/profiles.js +12 -0
- package/dist/surface/profiles.js.map +1 -1
- package/dist/surface/profiles.test.js +45 -1
- package/dist/surface/profiles.test.js.map +1 -1
- package/package.json +5 -5
- package/runtime/Tsonic.JSRuntime.dll +0 -0
- package/runtime/Tsonic.Runtime.dll +0 -0
- package/runtime/nodejs.dll +0 -0
|
@@ -17,6 +17,82 @@ const ensureUndefinedInType = (typeText) => {
|
|
|
17
17
|
return trimmed;
|
|
18
18
|
return `${trimmed} | undefined`;
|
|
19
19
|
};
|
|
20
|
+
const textContainsIdentifier = (text, identifier) => {
|
|
21
|
+
const escaped = identifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
22
|
+
return new RegExp(`(^|[^A-Za-z0-9_$])${escaped}([^A-Za-z0-9_$]|$)`).test(text);
|
|
23
|
+
};
|
|
24
|
+
const toRelativeImportSpecifier = (fromFile, targetFile) => {
|
|
25
|
+
const relative = posix.relative(posix.dirname(fromFile), targetFile);
|
|
26
|
+
if (relative.startsWith("."))
|
|
27
|
+
return relative;
|
|
28
|
+
return `./${relative}`;
|
|
29
|
+
};
|
|
30
|
+
const namespaceInternalImportSpecifier = (fromNamespace, targetNamespace) => {
|
|
31
|
+
return toRelativeImportSpecifier(posix.join(moduleNamespacePath(fromNamespace), "internal", "index.js"), posix.join(moduleNamespacePath(targetNamespace), "internal", "index.js"));
|
|
32
|
+
};
|
|
33
|
+
const namespaceFacadeImportSpecifier = (fromNamespace, targetNamespace) => {
|
|
34
|
+
return toRelativeImportSpecifier(`${moduleNamespacePath(fromNamespace)}.js`, `${moduleNamespacePath(targetNamespace)}.js`);
|
|
35
|
+
};
|
|
36
|
+
const resolveSourceTypeImportBinding = (opts) => {
|
|
37
|
+
const source = opts.imported.source.trim();
|
|
38
|
+
if (source === "@tsonic/core/types.js") {
|
|
39
|
+
return { ok: true, value: undefined };
|
|
40
|
+
}
|
|
41
|
+
if (!isRelativeModuleSpecifier(source)) {
|
|
42
|
+
return {
|
|
43
|
+
ok: true,
|
|
44
|
+
value: {
|
|
45
|
+
source,
|
|
46
|
+
importedName: opts.imported.importedName,
|
|
47
|
+
localName: opts.localName,
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const targetModule = resolveLocalModuleFile(source, opts.currentModuleKey, opts.modulesByFileKey);
|
|
52
|
+
if (!targetModule) {
|
|
53
|
+
return {
|
|
54
|
+
ok: false,
|
|
55
|
+
error: `Unable to resolve source type import '${opts.localName}' from '${source}' in ${opts.currentModuleKey}.\n` +
|
|
56
|
+
"First-party bindings generation requires public type dependencies to resolve deterministically.",
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
if (targetModule.namespace === opts.currentNamespace) {
|
|
60
|
+
return { ok: true, value: undefined };
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
ok: true,
|
|
64
|
+
value: {
|
|
65
|
+
source: opts.context === "internal"
|
|
66
|
+
? namespaceInternalImportSpecifier(opts.currentNamespace, targetModule.namespace)
|
|
67
|
+
: namespaceFacadeImportSpecifier(opts.currentNamespace, targetModule.namespace),
|
|
68
|
+
importedName: opts.imported.importedName,
|
|
69
|
+
localName: opts.localName,
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
const registerSourceTypeImportBinding = (registry, binding, namespace, moduleFilePath) => {
|
|
74
|
+
const existing = registry.get(binding.localName);
|
|
75
|
+
if (existing) {
|
|
76
|
+
if (existing.source !== binding.source ||
|
|
77
|
+
existing.importedName !== binding.importedName) {
|
|
78
|
+
return {
|
|
79
|
+
ok: false,
|
|
80
|
+
error: `Conflicting source type import alias '${binding.localName}' while generating namespace ${namespace} from ${moduleFilePath}.\n` +
|
|
81
|
+
`- ${existing.importedName} from '${existing.source}'\n` +
|
|
82
|
+
`- ${binding.importedName} from '${binding.source}'\n` +
|
|
83
|
+
"Disambiguate source type imports so generated bindings remain deterministic.",
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return { ok: true, value: undefined };
|
|
87
|
+
}
|
|
88
|
+
registry.set(binding.localName, binding);
|
|
89
|
+
return { ok: true, value: undefined };
|
|
90
|
+
};
|
|
91
|
+
const selectSourceTypeImportsForRenderedText = (renderedText, candidates) => {
|
|
92
|
+
return candidates
|
|
93
|
+
.filter((candidate) => textContainsIdentifier(renderedText, candidate.localName))
|
|
94
|
+
.sort((left, right) => left.localName.localeCompare(right.localName));
|
|
95
|
+
};
|
|
20
96
|
const applyWrappersToBaseType = (baseType, wrappers) => {
|
|
21
97
|
let expr = baseType.trim();
|
|
22
98
|
for (const w of wrappers.slice().reverse()) {
|
|
@@ -35,6 +111,11 @@ const sanitizeForBrand = (value) => {
|
|
|
35
111
|
const normalized = value.replace(/[^A-Za-z0-9_]/g, "_");
|
|
36
112
|
return normalized.length > 0 ? normalized : "_";
|
|
37
113
|
};
|
|
114
|
+
const renderBindingAliasMarker = (namespace, bindingAlias) => ` readonly ${JSON.stringify(`__tsonic_binding_alias_${namespace}.${bindingAlias}`)}?: never;`;
|
|
115
|
+
const isPortableMarkerMemberName = (name) => name === "__brand" ||
|
|
116
|
+
name.startsWith("__tsonic_type_") ||
|
|
117
|
+
name.startsWith("__tsonic_iface_") ||
|
|
118
|
+
name.startsWith("__tsonic_binding_alias_");
|
|
38
119
|
const printTypeParameters = (typeParameters) => {
|
|
39
120
|
if (!typeParameters || typeParameters.length === 0)
|
|
40
121
|
return "";
|
|
@@ -53,7 +134,7 @@ const normalizeTypeReferenceName = (name, arity) => {
|
|
|
53
134
|
}
|
|
54
135
|
return `${backtickNormalized}_${arity}`;
|
|
55
136
|
};
|
|
56
|
-
const renderReferenceType = (referenceName, typeArguments, typeParametersInScope) => {
|
|
137
|
+
const renderReferenceType = (referenceName, typeArguments, typeParametersInScope, localTypeNameRemaps = new Map()) => {
|
|
57
138
|
if (typeParametersInScope.includes(referenceName))
|
|
58
139
|
return referenceName;
|
|
59
140
|
if (referenceName === "unknown")
|
|
@@ -68,7 +149,8 @@ const renderReferenceType = (referenceName, typeArguments, typeParametersInScope
|
|
|
68
149
|
return "boolean";
|
|
69
150
|
if (referenceName === "number")
|
|
70
151
|
return "number";
|
|
71
|
-
|
|
152
|
+
const effectiveReferenceName = localTypeNameRemaps.get(referenceName) ?? referenceName;
|
|
153
|
+
let normalizedName = normalizeTypeReferenceName(effectiveReferenceName);
|
|
72
154
|
if (typeArguments && typeArguments.length > 0) {
|
|
73
155
|
const arityMatch = normalizedName.match(/_(\d+)$/);
|
|
74
156
|
if (arityMatch &&
|
|
@@ -86,80 +168,124 @@ const renderReferenceType = (referenceName, typeArguments, typeParametersInScope
|
|
|
86
168
|
if (!typeArguments || typeArguments.length === 0)
|
|
87
169
|
return normalizedName;
|
|
88
170
|
return `${normalizedName}<${typeArguments
|
|
89
|
-
.map((arg) => renderPortableType(arg, typeParametersInScope))
|
|
171
|
+
.map((arg) => renderPortableType(arg, typeParametersInScope, localTypeNameRemaps))
|
|
90
172
|
.join(", ")}>`;
|
|
91
173
|
};
|
|
92
|
-
const renderPortableType = (type, typeParametersInScope = []) => {
|
|
174
|
+
const renderPortableType = (type, typeParametersInScope = [], localTypeNameRemaps = new Map(), anonymousStructuralAliases = new Map()) => {
|
|
175
|
+
const renderPortableShapeType = (shapeType, shapeTypeParametersInScope = []) => {
|
|
176
|
+
if (!shapeType)
|
|
177
|
+
return "object";
|
|
178
|
+
switch (shapeType.kind) {
|
|
179
|
+
case "primitiveType":
|
|
180
|
+
return shapeType.name;
|
|
181
|
+
case "literalType":
|
|
182
|
+
return typeof shapeType.value === "string"
|
|
183
|
+
? JSON.stringify(shapeType.value)
|
|
184
|
+
: String(shapeType.value);
|
|
185
|
+
case "voidType":
|
|
186
|
+
return "void";
|
|
187
|
+
case "neverType":
|
|
188
|
+
return "never";
|
|
189
|
+
case "unknownType":
|
|
190
|
+
case "anyType":
|
|
191
|
+
return "unknown";
|
|
192
|
+
case "typeParameterType":
|
|
193
|
+
return shapeType.name;
|
|
194
|
+
case "arrayType":
|
|
195
|
+
return `${renderPortableShapeType(shapeType.elementType, shapeTypeParametersInScope)}[]`;
|
|
196
|
+
case "tupleType":
|
|
197
|
+
return `[${shapeType.elementTypes
|
|
198
|
+
.map((item) => renderPortableShapeType(item, shapeTypeParametersInScope))
|
|
199
|
+
.join(", ")}]`;
|
|
200
|
+
case "unionType":
|
|
201
|
+
return shapeType.types
|
|
202
|
+
.map((item) => renderPortableShapeType(item, shapeTypeParametersInScope))
|
|
203
|
+
.join(" | ");
|
|
204
|
+
case "intersectionType":
|
|
205
|
+
return shapeType.types
|
|
206
|
+
.map((item) => renderPortableShapeType(item, shapeTypeParametersInScope))
|
|
207
|
+
.join(" & ");
|
|
208
|
+
case "dictionaryType":
|
|
209
|
+
return `Record<${renderPortableShapeType(shapeType.keyType, shapeTypeParametersInScope)}, ${renderPortableShapeType(shapeType.valueType, shapeTypeParametersInScope)}>`;
|
|
210
|
+
case "functionType":
|
|
211
|
+
return `(${shapeType.parameters
|
|
212
|
+
.map((parameter, index) => {
|
|
213
|
+
const parameterName = parameter.pattern.kind === "identifierPattern"
|
|
214
|
+
? parameter.pattern.name
|
|
215
|
+
: `p${index + 1}`;
|
|
216
|
+
return `${parameterName}: ${renderPortableShapeType(parameter.type, shapeTypeParametersInScope)}`;
|
|
217
|
+
})
|
|
218
|
+
.join(", ")}) => ${renderPortableShapeType(shapeType.returnType, shapeTypeParametersInScope)}`;
|
|
219
|
+
case "objectType":
|
|
220
|
+
return `{ ${shapeType.members
|
|
221
|
+
.filter((member) => !isPortableMarkerMemberName(member.name))
|
|
222
|
+
.map((member) => {
|
|
223
|
+
if (member.kind === "methodSignature") {
|
|
224
|
+
return `${member.name}${printTypeParameters(member.typeParameters)}(${member.parameters
|
|
225
|
+
.map((parameter, index) => {
|
|
226
|
+
const parameterName = parameter.pattern.kind === "identifierPattern"
|
|
227
|
+
? parameter.pattern.name
|
|
228
|
+
: `p${index + 1}`;
|
|
229
|
+
const optionalMark = parameter.isOptional ? "?" : "";
|
|
230
|
+
return `${parameterName}${optionalMark}: ${renderPortableShapeType(parameter.type, shapeTypeParametersInScope)}`;
|
|
231
|
+
})
|
|
232
|
+
.join(", ")}): ${renderPortableShapeType(member.returnType, shapeTypeParametersInScope)}`;
|
|
233
|
+
}
|
|
234
|
+
const optionalMark = member.isOptional ? "?" : "";
|
|
235
|
+
const readonlyMark = member.isReadonly ? "readonly " : "";
|
|
236
|
+
return `${readonlyMark}${member.name}${optionalMark}: ${renderPortableShapeType(member.type, shapeTypeParametersInScope)}`;
|
|
237
|
+
})
|
|
238
|
+
.join("; ")} }`;
|
|
239
|
+
case "referenceType":
|
|
240
|
+
return renderReferenceType(shapeType.name, shapeType.typeArguments, shapeTypeParametersInScope, localTypeNameRemaps);
|
|
241
|
+
default:
|
|
242
|
+
return "object";
|
|
243
|
+
}
|
|
244
|
+
};
|
|
93
245
|
if (!type)
|
|
94
246
|
return "object";
|
|
95
247
|
switch (type.kind) {
|
|
96
|
-
case "
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
return
|
|
106
|
-
|
|
107
|
-
case "anyType":
|
|
108
|
-
return "unknown";
|
|
109
|
-
case "typeParameterType":
|
|
110
|
-
return type.name;
|
|
248
|
+
case "objectType": {
|
|
249
|
+
const shape = renderPortableShapeType(type, typeParametersInScope);
|
|
250
|
+
const alias = anonymousStructuralAliases.get(shape);
|
|
251
|
+
if (alias) {
|
|
252
|
+
const typeArgs = alias.typeParameters.length > 0
|
|
253
|
+
? `<${alias.typeParameters.join(", ")}>`
|
|
254
|
+
: "";
|
|
255
|
+
return `${alias.name}${typeArgs}`;
|
|
256
|
+
}
|
|
257
|
+
return shape;
|
|
258
|
+
}
|
|
111
259
|
case "arrayType":
|
|
112
|
-
return `${renderPortableType(type.elementType, typeParametersInScope)}[]`;
|
|
260
|
+
return `${renderPortableType(type.elementType, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases)}[]`;
|
|
113
261
|
case "tupleType":
|
|
114
262
|
return `[${type.elementTypes
|
|
115
|
-
.map((item) => renderPortableType(item, typeParametersInScope))
|
|
263
|
+
.map((item) => renderPortableType(item, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases))
|
|
116
264
|
.join(", ")}]`;
|
|
117
265
|
case "unionType":
|
|
118
266
|
return type.types
|
|
119
|
-
.map((item) => renderPortableType(item, typeParametersInScope))
|
|
267
|
+
.map((item) => renderPortableType(item, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases))
|
|
120
268
|
.join(" | ");
|
|
121
269
|
case "intersectionType":
|
|
122
270
|
return type.types
|
|
123
|
-
.map((item) => renderPortableType(item, typeParametersInScope))
|
|
271
|
+
.map((item) => renderPortableType(item, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases))
|
|
124
272
|
.join(" & ");
|
|
125
273
|
case "dictionaryType":
|
|
126
|
-
return `Record<${renderPortableType(type.keyType, typeParametersInScope)}, ${renderPortableType(type.valueType, typeParametersInScope)}>`;
|
|
274
|
+
return `Record<${renderPortableType(type.keyType, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases)}, ${renderPortableType(type.valueType, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases)}>`;
|
|
127
275
|
case "functionType":
|
|
128
276
|
return `(${type.parameters
|
|
129
277
|
.map((parameter, index) => {
|
|
130
278
|
const parameterName = parameter.pattern.kind === "identifierPattern"
|
|
131
279
|
? parameter.pattern.name
|
|
132
280
|
: `p${index + 1}`;
|
|
133
|
-
return `${parameterName}: ${renderPortableType(parameter.type, typeParametersInScope)}`;
|
|
281
|
+
return `${parameterName}: ${renderPortableType(parameter.type, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases)}`;
|
|
134
282
|
})
|
|
135
|
-
.join(", ")}) => ${renderPortableType(type.returnType, typeParametersInScope)}`;
|
|
136
|
-
case "objectType":
|
|
137
|
-
return `{ ${type.members
|
|
138
|
-
.map((member) => {
|
|
139
|
-
if (member.kind === "methodSignature") {
|
|
140
|
-
return `${member.name}${printTypeParameters(member.typeParameters)}(${member.parameters
|
|
141
|
-
.map((parameter, index) => {
|
|
142
|
-
const parameterName = parameter.pattern.kind === "identifierPattern"
|
|
143
|
-
? parameter.pattern.name
|
|
144
|
-
: `p${index + 1}`;
|
|
145
|
-
const optionalMark = parameter.isOptional ? "?" : "";
|
|
146
|
-
return `${parameterName}${optionalMark}: ${renderPortableType(parameter.type, typeParametersInScope)}`;
|
|
147
|
-
})
|
|
148
|
-
.join(", ")}): ${renderPortableType(member.returnType, typeParametersInScope)}`;
|
|
149
|
-
}
|
|
150
|
-
const optionalMark = member.isOptional ? "?" : "";
|
|
151
|
-
const readonlyMark = member.isReadonly ? "readonly " : "";
|
|
152
|
-
return `${readonlyMark}${member.name}${optionalMark}: ${renderPortableType(member.type, typeParametersInScope)}`;
|
|
153
|
-
})
|
|
154
|
-
.join("; ")} }`;
|
|
155
|
-
case "referenceType": {
|
|
156
|
-
return renderReferenceType(type.name, type.typeArguments, typeParametersInScope);
|
|
157
|
-
}
|
|
283
|
+
.join(", ")}) => ${renderPortableType(type.returnType, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases)}`;
|
|
158
284
|
default:
|
|
159
|
-
return
|
|
285
|
+
return renderPortableShapeType(type, typeParametersInScope);
|
|
160
286
|
}
|
|
161
287
|
};
|
|
162
|
-
const renderUnknownParameters = (parameters, typeParametersInScope) => {
|
|
288
|
+
const renderUnknownParameters = (parameters, typeParametersInScope, localTypeNameRemaps = new Map(), anonymousStructuralAliases = new Map()) => {
|
|
163
289
|
return parameters
|
|
164
290
|
.map((parameter, index) => {
|
|
165
291
|
const baseName = parameter.pattern.kind === "identifierPattern"
|
|
@@ -167,7 +293,7 @@ const renderUnknownParameters = (parameters, typeParametersInScope) => {
|
|
|
167
293
|
: `p${index + 1}`;
|
|
168
294
|
const restPrefix = parameter.isRest ? "..." : "";
|
|
169
295
|
const optionalMark = parameter.isOptional && !parameter.isRest ? "?" : "";
|
|
170
|
-
const parameterType = renderPortableType(parameter.type, typeParametersInScope);
|
|
296
|
+
const parameterType = renderPortableType(parameter.type, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases);
|
|
171
297
|
const typeSuffix = parameter.isRest
|
|
172
298
|
? `${parameterType}[]`
|
|
173
299
|
: parameterType;
|
|
@@ -175,13 +301,405 @@ const renderUnknownParameters = (parameters, typeParametersInScope) => {
|
|
|
175
301
|
})
|
|
176
302
|
.join(", ");
|
|
177
303
|
};
|
|
178
|
-
const renderMethodSignature = (name, typeParameters, parameters, returnType) => {
|
|
304
|
+
const renderMethodSignature = (name, typeParameters, parameters, returnType, localTypeNameRemaps = new Map(), anonymousStructuralAliases = new Map()) => {
|
|
179
305
|
const typeParametersText = printTypeParameters(typeParameters);
|
|
180
306
|
const typeParameterNames = typeParameters?.map((typeParameter) => typeParameter.name) ?? [];
|
|
181
|
-
const parametersText = renderUnknownParameters(parameters, typeParameterNames);
|
|
182
|
-
const returnTypeText = renderPortableType(returnType, typeParameterNames);
|
|
307
|
+
const parametersText = renderUnknownParameters(parameters, typeParameterNames, localTypeNameRemaps, anonymousStructuralAliases);
|
|
308
|
+
const returnTypeText = renderPortableType(returnType, typeParameterNames, localTypeNameRemaps, anonymousStructuralAliases);
|
|
183
309
|
return `${name}${typeParametersText}(${parametersText}): ${returnTypeText};`;
|
|
184
310
|
};
|
|
311
|
+
const renderSourceTypeNodeForAliasLookup = (node, localTypeNameRemaps) => {
|
|
312
|
+
switch (node.kind) {
|
|
313
|
+
case ts.SyntaxKind.StringKeyword:
|
|
314
|
+
return "string";
|
|
315
|
+
case ts.SyntaxKind.NumberKeyword:
|
|
316
|
+
return "number";
|
|
317
|
+
case ts.SyntaxKind.BooleanKeyword:
|
|
318
|
+
return "boolean";
|
|
319
|
+
case ts.SyntaxKind.VoidKeyword:
|
|
320
|
+
return "void";
|
|
321
|
+
case ts.SyntaxKind.NeverKeyword:
|
|
322
|
+
return "never";
|
|
323
|
+
case ts.SyntaxKind.UnknownKeyword:
|
|
324
|
+
return "unknown";
|
|
325
|
+
case ts.SyntaxKind.AnyKeyword:
|
|
326
|
+
return "unknown";
|
|
327
|
+
case ts.SyntaxKind.NullKeyword:
|
|
328
|
+
return "null";
|
|
329
|
+
case ts.SyntaxKind.UndefinedKeyword:
|
|
330
|
+
return "undefined";
|
|
331
|
+
}
|
|
332
|
+
if (ts.isParenthesizedTypeNode(node)) {
|
|
333
|
+
return `(${renderSourceTypeNodeForAliasLookup(node.type, localTypeNameRemaps)})`;
|
|
334
|
+
}
|
|
335
|
+
if (ts.isArrayTypeNode(node)) {
|
|
336
|
+
return `${renderSourceTypeNodeForAliasLookup(node.elementType, localTypeNameRemaps)}[]`;
|
|
337
|
+
}
|
|
338
|
+
if (ts.isTupleTypeNode(node)) {
|
|
339
|
+
return `[${node.elements
|
|
340
|
+
.map((element) => renderSourceTypeNodeForAliasLookup(element, localTypeNameRemaps))
|
|
341
|
+
.join(", ")}]`;
|
|
342
|
+
}
|
|
343
|
+
if (ts.isUnionTypeNode(node)) {
|
|
344
|
+
return node.types
|
|
345
|
+
.map((part) => renderSourceTypeNodeForAliasLookup(part, localTypeNameRemaps))
|
|
346
|
+
.join(" | ");
|
|
347
|
+
}
|
|
348
|
+
if (ts.isIntersectionTypeNode(node)) {
|
|
349
|
+
return node.types
|
|
350
|
+
.map((part) => renderSourceTypeNodeForAliasLookup(part, localTypeNameRemaps))
|
|
351
|
+
.join(" & ");
|
|
352
|
+
}
|
|
353
|
+
if (ts.isLiteralTypeNode(node)) {
|
|
354
|
+
return node.getText();
|
|
355
|
+
}
|
|
356
|
+
if (ts.isTypeReferenceNode(node)) {
|
|
357
|
+
const typeNameText = node.typeName.getText();
|
|
358
|
+
const rewrittenTypeName = rewriteSourceTypeText(typeNameText, localTypeNameRemaps);
|
|
359
|
+
if (!node.typeArguments || node.typeArguments.length === 0) {
|
|
360
|
+
return rewrittenTypeName;
|
|
361
|
+
}
|
|
362
|
+
return `${rewrittenTypeName}<${node.typeArguments
|
|
363
|
+
.map((argument) => renderSourceTypeNodeForAliasLookup(argument, localTypeNameRemaps))
|
|
364
|
+
.join(", ")}>`;
|
|
365
|
+
}
|
|
366
|
+
if (ts.isTypeLiteralNode(node)) {
|
|
367
|
+
return `{ ${node.members
|
|
368
|
+
.flatMap((member) => {
|
|
369
|
+
if (ts.isPropertySignature(member)) {
|
|
370
|
+
const propertyName = ts.isIdentifier(member.name)
|
|
371
|
+
? member.name.text
|
|
372
|
+
: ts.isStringLiteral(member.name)
|
|
373
|
+
? member.name.text
|
|
374
|
+
: undefined;
|
|
375
|
+
if (!propertyName || !member.type)
|
|
376
|
+
return [];
|
|
377
|
+
const readonlyMark = (member.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ReadonlyKeyword) ?? false)
|
|
378
|
+
? "readonly "
|
|
379
|
+
: "";
|
|
380
|
+
const propertyTypeText = member.questionToken
|
|
381
|
+
? ensureUndefinedInType(renderSourceTypeNodeForAliasLookup(member.type, localTypeNameRemaps))
|
|
382
|
+
: renderSourceTypeNodeForAliasLookup(member.type, localTypeNameRemaps);
|
|
383
|
+
return [`${readonlyMark}${propertyName}: ${propertyTypeText}`];
|
|
384
|
+
}
|
|
385
|
+
if (ts.isMethodSignature(member)) {
|
|
386
|
+
const methodName = ts.isIdentifier(member.name)
|
|
387
|
+
? member.name.text
|
|
388
|
+
: ts.isStringLiteral(member.name)
|
|
389
|
+
? member.name.text
|
|
390
|
+
: undefined;
|
|
391
|
+
if (!methodName)
|
|
392
|
+
return [];
|
|
393
|
+
const typeParametersText = member.typeParameters
|
|
394
|
+
? `<${member.typeParameters
|
|
395
|
+
.map((typeParameter) => typeParameter.name.text)
|
|
396
|
+
.join(", ")}>`
|
|
397
|
+
: "";
|
|
398
|
+
const parametersText = member.parameters
|
|
399
|
+
.map((parameter, index) => {
|
|
400
|
+
const parameterName = ts.isIdentifier(parameter.name)
|
|
401
|
+
? parameter.name.text
|
|
402
|
+
: `p${index + 1}`;
|
|
403
|
+
const optionalMark = parameter.questionToken ? "?" : "";
|
|
404
|
+
const restPrefix = parameter.dotDotDotToken ? "..." : "";
|
|
405
|
+
const parameterType = parameter.type
|
|
406
|
+
? renderSourceTypeNodeForAliasLookup(parameter.type, localTypeNameRemaps)
|
|
407
|
+
: "unknown";
|
|
408
|
+
return `${restPrefix}${parameterName}${optionalMark}: ${parameterType}`;
|
|
409
|
+
})
|
|
410
|
+
.join(", ");
|
|
411
|
+
const returnType = member.type
|
|
412
|
+
? renderSourceTypeNodeForAliasLookup(member.type, localTypeNameRemaps)
|
|
413
|
+
: "void";
|
|
414
|
+
return [
|
|
415
|
+
`${methodName}${typeParametersText}(${parametersText}): ${returnType}`,
|
|
416
|
+
];
|
|
417
|
+
}
|
|
418
|
+
return [];
|
|
419
|
+
})
|
|
420
|
+
.join("; ")} }`;
|
|
421
|
+
}
|
|
422
|
+
return node.getText();
|
|
423
|
+
};
|
|
424
|
+
const rewriteSourceTypeText = (typeText, localTypeNameRemaps, anonymousStructuralAliases = new Map()) => {
|
|
425
|
+
const sourceFile = ts.createSourceFile("__tsonic_source_type__.ts", `type __T = ${typeText};`, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
426
|
+
const statement = sourceFile.statements[0];
|
|
427
|
+
if (!statement || !ts.isTypeAliasDeclaration(statement))
|
|
428
|
+
return typeText;
|
|
429
|
+
const transformer = (context) => {
|
|
430
|
+
const visit = (node) => {
|
|
431
|
+
if (ts.isTypeReferenceNode(node) && ts.isIdentifier(node.typeName)) {
|
|
432
|
+
const remappedName = localTypeNameRemaps.get(node.typeName.text);
|
|
433
|
+
if (remappedName) {
|
|
434
|
+
return ts.factory.updateTypeReferenceNode(node, ts.factory.createIdentifier(remappedName), node.typeArguments);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
if (anonymousStructuralAliases.size > 0 && ts.isTypeLiteralNode(node)) {
|
|
438
|
+
const alias = anonymousStructuralAliases.get(renderSourceTypeNodeForAliasLookup(node, localTypeNameRemaps));
|
|
439
|
+
if (alias) {
|
|
440
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(alias.name), alias.typeParameters.map((typeParameter) => ts.factory.createTypeReferenceNode(typeParameter)));
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
return ts.visitEachChild(node, visit, context);
|
|
444
|
+
};
|
|
445
|
+
return (node) => ts.visitNode(node, visit);
|
|
446
|
+
};
|
|
447
|
+
const transformed = ts.transform(statement.type, [transformer])
|
|
448
|
+
.transformed[0];
|
|
449
|
+
if (!transformed)
|
|
450
|
+
return typeText;
|
|
451
|
+
const printer = ts.createPrinter({ removeComments: true });
|
|
452
|
+
return printer.printNode(ts.EmitHint.Unspecified, transformed, sourceFile);
|
|
453
|
+
};
|
|
454
|
+
const selectPreferredSourceFunctionSignature = (opts) => {
|
|
455
|
+
const targetTypeParameterCount = opts.declaration.typeParameters?.length ?? 0;
|
|
456
|
+
const targetParameterCount = opts.declaration.parameters.length;
|
|
457
|
+
const exact = opts.sourceSignatures.find((signature) => {
|
|
458
|
+
return (signature.parameters.length === targetParameterCount &&
|
|
459
|
+
signature.typeParameterCount === targetTypeParameterCount);
|
|
460
|
+
});
|
|
461
|
+
return exact ?? opts.sourceSignatures[0];
|
|
462
|
+
};
|
|
463
|
+
const renderSourceFunctionSignature = (opts) => {
|
|
464
|
+
const sourceSignature = selectPreferredSourceFunctionSignature({
|
|
465
|
+
declaration: opts.declaration,
|
|
466
|
+
sourceSignatures: opts.sourceSignatures,
|
|
467
|
+
});
|
|
468
|
+
if (!sourceSignature)
|
|
469
|
+
return undefined;
|
|
470
|
+
const parametersText = sourceSignature.parameters
|
|
471
|
+
.map((parameter) => `${parameter.prefixText}${rewriteSourceTypeText(parameter.typeText, opts.localTypeNameRemaps, opts.anonymousStructuralAliases)}`)
|
|
472
|
+
.join(", ");
|
|
473
|
+
return {
|
|
474
|
+
typeParametersText: sourceSignature.typeParametersText,
|
|
475
|
+
parametersText,
|
|
476
|
+
returnTypeText: rewriteSourceTypeText(sourceSignature.returnTypeText, opts.localTypeNameRemaps, opts.anonymousStructuralAliases),
|
|
477
|
+
};
|
|
478
|
+
};
|
|
479
|
+
const renderSourceValueType = (sourceType, localTypeNameRemaps, anonymousStructuralAliases = new Map()) => !sourceType
|
|
480
|
+
? undefined
|
|
481
|
+
: rewriteSourceTypeText(sourceType.typeText, localTypeNameRemaps, anonymousStructuralAliases);
|
|
482
|
+
const renderSourceFunctionType = (opts) => {
|
|
483
|
+
const sourceSignature = opts.sourceSignatures[0];
|
|
484
|
+
if (!sourceSignature)
|
|
485
|
+
return undefined;
|
|
486
|
+
const parametersText = sourceSignature.parameters
|
|
487
|
+
.map((parameter) => `${parameter.prefixText}${rewriteSourceTypeText(parameter.typeText, opts.localTypeNameRemaps, opts.anonymousStructuralAliases)}`)
|
|
488
|
+
.join(", ");
|
|
489
|
+
return `${sourceSignature.typeParametersText}(${parametersText}) => ${rewriteSourceTypeText(sourceSignature.returnTypeText, opts.localTypeNameRemaps, opts.anonymousStructuralAliases)}`;
|
|
490
|
+
};
|
|
491
|
+
const isGeneratedStructuralHelperName = (name) => name.startsWith("__Anon_") || /__\d+$/.test(name);
|
|
492
|
+
const buildAnonymousStructuralAliasMap = (plan) => {
|
|
493
|
+
const aliases = new Map();
|
|
494
|
+
const registerAnonymousClass = (localName, declaration) => {
|
|
495
|
+
if (!isGeneratedStructuralHelperName(localName))
|
|
496
|
+
return;
|
|
497
|
+
const members = [];
|
|
498
|
+
for (const member of declaration.members) {
|
|
499
|
+
if (member.kind === "propertyDeclaration") {
|
|
500
|
+
if (isPortableMarkerMemberName(member.name))
|
|
501
|
+
continue;
|
|
502
|
+
members.push({
|
|
503
|
+
kind: "propertySignature",
|
|
504
|
+
name: member.name,
|
|
505
|
+
type: member.type ?? { kind: "unknownType" },
|
|
506
|
+
isOptional: false,
|
|
507
|
+
isReadonly: member.isReadonly,
|
|
508
|
+
});
|
|
509
|
+
continue;
|
|
510
|
+
}
|
|
511
|
+
if (member.kind === "methodDeclaration") {
|
|
512
|
+
if (isPortableMarkerMemberName(member.name))
|
|
513
|
+
continue;
|
|
514
|
+
members.push({
|
|
515
|
+
kind: "methodSignature",
|
|
516
|
+
name: member.name,
|
|
517
|
+
parameters: member.parameters,
|
|
518
|
+
returnType: member.returnType,
|
|
519
|
+
typeParameters: member.typeParameters,
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
const shape = renderPortableType({ kind: "objectType", members }, declaration.typeParameters?.map((typeParameter) => typeParameter.name) ??
|
|
524
|
+
[], new Map(), new Map());
|
|
525
|
+
const existing = aliases.get(shape) ?? [];
|
|
526
|
+
existing.push({
|
|
527
|
+
name: localName,
|
|
528
|
+
typeParameters: declaration.typeParameters?.map((typeParameter) => typeParameter.name) ?? [],
|
|
529
|
+
});
|
|
530
|
+
aliases.set(shape, existing);
|
|
531
|
+
};
|
|
532
|
+
for (const symbol of plan.typeDeclarations) {
|
|
533
|
+
if (symbol.kind !== "class" ||
|
|
534
|
+
symbol.declaration.kind !== "classDeclaration") {
|
|
535
|
+
continue;
|
|
536
|
+
}
|
|
537
|
+
registerAnonymousClass(symbol.localName, symbol.declaration);
|
|
538
|
+
}
|
|
539
|
+
for (const helper of plan.internalHelperTypeDeclarations) {
|
|
540
|
+
if (helper.kind !== "class")
|
|
541
|
+
continue;
|
|
542
|
+
registerAnonymousClass(helper.emittedName, helper.declaration);
|
|
543
|
+
}
|
|
544
|
+
const uniqueAliases = new Map();
|
|
545
|
+
for (const [shape, candidates] of aliases.entries()) {
|
|
546
|
+
if (candidates.length !== 1)
|
|
547
|
+
continue;
|
|
548
|
+
const onlyCandidate = candidates[0];
|
|
549
|
+
if (!onlyCandidate)
|
|
550
|
+
continue;
|
|
551
|
+
uniqueAliases.set(shape, onlyCandidate);
|
|
552
|
+
}
|
|
553
|
+
return uniqueAliases;
|
|
554
|
+
};
|
|
555
|
+
const collectReferencedPortableTypeNames = (type, typeParametersInScope, out) => {
|
|
556
|
+
if (!type)
|
|
557
|
+
return;
|
|
558
|
+
switch (type.kind) {
|
|
559
|
+
case "primitiveType":
|
|
560
|
+
case "literalType":
|
|
561
|
+
case "voidType":
|
|
562
|
+
case "neverType":
|
|
563
|
+
case "unknownType":
|
|
564
|
+
case "anyType":
|
|
565
|
+
return;
|
|
566
|
+
case "typeParameterType":
|
|
567
|
+
if (!typeParametersInScope.has(type.name)) {
|
|
568
|
+
out.add(type.name);
|
|
569
|
+
}
|
|
570
|
+
return;
|
|
571
|
+
case "arrayType":
|
|
572
|
+
collectReferencedPortableTypeNames(type.elementType, typeParametersInScope, out);
|
|
573
|
+
return;
|
|
574
|
+
case "tupleType":
|
|
575
|
+
for (const element of type.elementTypes) {
|
|
576
|
+
collectReferencedPortableTypeNames(element, typeParametersInScope, out);
|
|
577
|
+
}
|
|
578
|
+
return;
|
|
579
|
+
case "unionType":
|
|
580
|
+
case "intersectionType":
|
|
581
|
+
for (const member of type.types) {
|
|
582
|
+
collectReferencedPortableTypeNames(member, typeParametersInScope, out);
|
|
583
|
+
}
|
|
584
|
+
return;
|
|
585
|
+
case "dictionaryType":
|
|
586
|
+
collectReferencedPortableTypeNames(type.keyType, typeParametersInScope, out);
|
|
587
|
+
collectReferencedPortableTypeNames(type.valueType, typeParametersInScope, out);
|
|
588
|
+
return;
|
|
589
|
+
case "functionType":
|
|
590
|
+
for (const parameter of type.parameters) {
|
|
591
|
+
collectReferencedPortableTypeNames(parameter.type, typeParametersInScope, out);
|
|
592
|
+
}
|
|
593
|
+
collectReferencedPortableTypeNames(type.returnType, typeParametersInScope, out);
|
|
594
|
+
return;
|
|
595
|
+
case "objectType":
|
|
596
|
+
for (const member of type.members) {
|
|
597
|
+
if (member.kind === "propertySignature") {
|
|
598
|
+
collectReferencedPortableTypeNames(member.type, typeParametersInScope, out);
|
|
599
|
+
continue;
|
|
600
|
+
}
|
|
601
|
+
const nestedTypeParameters = new Set(typeParametersInScope);
|
|
602
|
+
for (const typeParameter of member.typeParameters ?? []) {
|
|
603
|
+
nestedTypeParameters.add(typeParameter.name);
|
|
604
|
+
}
|
|
605
|
+
for (const parameter of member.parameters) {
|
|
606
|
+
collectReferencedPortableTypeNames(parameter.type, nestedTypeParameters, out);
|
|
607
|
+
}
|
|
608
|
+
collectReferencedPortableTypeNames(member.returnType, nestedTypeParameters, out);
|
|
609
|
+
}
|
|
610
|
+
return;
|
|
611
|
+
case "referenceType":
|
|
612
|
+
{
|
|
613
|
+
const renderedName = renderReferenceType(type.name, type.typeArguments, []);
|
|
614
|
+
const baseName = renderedName.split("<")[0];
|
|
615
|
+
if (!baseName)
|
|
616
|
+
return;
|
|
617
|
+
out.add(baseName);
|
|
618
|
+
}
|
|
619
|
+
for (const typeArgument of type.typeArguments ?? []) {
|
|
620
|
+
collectReferencedPortableTypeNames(typeArgument, typeParametersInScope, out);
|
|
621
|
+
}
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
const collectReferencedPortableTypesFromParameters = (parameters, typeParametersInScope, out) => {
|
|
626
|
+
for (const parameter of parameters) {
|
|
627
|
+
collectReferencedPortableTypeNames(parameter.type, typeParametersInScope, out);
|
|
628
|
+
}
|
|
629
|
+
};
|
|
630
|
+
const collectReferencedPortableTypeNamesFromDeclaration = (declaration, out) => {
|
|
631
|
+
switch (declaration.kind) {
|
|
632
|
+
case "enumDeclaration":
|
|
633
|
+
return;
|
|
634
|
+
case "typeAliasDeclaration": {
|
|
635
|
+
const typeParametersInScope = new Set((declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name));
|
|
636
|
+
collectReferencedPortableTypeNames(declaration.type, typeParametersInScope, out);
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
case "interfaceDeclaration": {
|
|
640
|
+
const typeParametersInScope = new Set((declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name));
|
|
641
|
+
for (const baseType of declaration.extends) {
|
|
642
|
+
collectReferencedPortableTypeNames(baseType, typeParametersInScope, out);
|
|
643
|
+
}
|
|
644
|
+
for (const member of declaration.members) {
|
|
645
|
+
if (member.kind === "propertySignature") {
|
|
646
|
+
collectReferencedPortableTypeNames(member.type, typeParametersInScope, out);
|
|
647
|
+
continue;
|
|
648
|
+
}
|
|
649
|
+
const nestedTypeParameters = new Set(typeParametersInScope);
|
|
650
|
+
for (const typeParameter of member.typeParameters ?? []) {
|
|
651
|
+
nestedTypeParameters.add(typeParameter.name);
|
|
652
|
+
}
|
|
653
|
+
collectReferencedPortableTypesFromParameters(member.parameters, nestedTypeParameters, out);
|
|
654
|
+
collectReferencedPortableTypeNames(member.returnType, nestedTypeParameters, out);
|
|
655
|
+
}
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
case "classDeclaration": {
|
|
659
|
+
const typeParametersInScope = new Set((declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name));
|
|
660
|
+
if (declaration.superClass) {
|
|
661
|
+
collectReferencedPortableTypeNames(declaration.superClass, typeParametersInScope, out);
|
|
662
|
+
}
|
|
663
|
+
for (const implementedType of declaration.implements) {
|
|
664
|
+
collectReferencedPortableTypeNames(implementedType, typeParametersInScope, out);
|
|
665
|
+
}
|
|
666
|
+
for (const member of declaration.members) {
|
|
667
|
+
switch (member.kind) {
|
|
668
|
+
case "constructorDeclaration":
|
|
669
|
+
collectReferencedPortableTypesFromParameters(member.parameters, typeParametersInScope, out);
|
|
670
|
+
continue;
|
|
671
|
+
case "propertyDeclaration":
|
|
672
|
+
collectReferencedPortableTypeNames(member.type, typeParametersInScope, out);
|
|
673
|
+
continue;
|
|
674
|
+
case "methodDeclaration": {
|
|
675
|
+
const nestedTypeParameters = new Set(typeParametersInScope);
|
|
676
|
+
for (const typeParameter of member.typeParameters ?? []) {
|
|
677
|
+
nestedTypeParameters.add(typeParameter.name);
|
|
678
|
+
}
|
|
679
|
+
collectReferencedPortableTypesFromParameters(member.parameters, nestedTypeParameters, out);
|
|
680
|
+
collectReferencedPortableTypeNames(member.returnType, nestedTypeParameters, out);
|
|
681
|
+
continue;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
};
|
|
689
|
+
const classifyLocalTypeDeclarationKind = (statement) => {
|
|
690
|
+
switch (statement.kind) {
|
|
691
|
+
case "classDeclaration":
|
|
692
|
+
return "class";
|
|
693
|
+
case "interfaceDeclaration":
|
|
694
|
+
return "interface";
|
|
695
|
+
case "enumDeclaration":
|
|
696
|
+
return "enum";
|
|
697
|
+
case "typeAliasDeclaration":
|
|
698
|
+
return "typeAlias";
|
|
699
|
+
default:
|
|
700
|
+
return undefined;
|
|
701
|
+
}
|
|
702
|
+
};
|
|
185
703
|
const declarationNameOf = (statement) => {
|
|
186
704
|
switch (statement.kind) {
|
|
187
705
|
case "functionDeclaration":
|
|
@@ -328,6 +846,22 @@ const collectModuleExports = (module, modulesByFileKey) => {
|
|
|
328
846
|
value: exportedSymbols.sort((left, right) => left.exportName.localeCompare(right.exportName)),
|
|
329
847
|
};
|
|
330
848
|
};
|
|
849
|
+
const finalizeCrossNamespaceReexports = (grouped) => {
|
|
850
|
+
const dtsStatements = [];
|
|
851
|
+
const jsValueStatements = [];
|
|
852
|
+
for (const [key, specs] of Array.from(grouped.entries()).sort((a, b) => a[0].localeCompare(b[0]))) {
|
|
853
|
+
const [moduleSpecifier, kind] = key.split("|");
|
|
854
|
+
const unique = Array.from(new Set(specs)).sort((a, b) => a.localeCompare(b));
|
|
855
|
+
if (kind === "type") {
|
|
856
|
+
dtsStatements.push(`export type { ${unique.join(", ")} } from '${moduleSpecifier}';`);
|
|
857
|
+
continue;
|
|
858
|
+
}
|
|
859
|
+
const statement = `export { ${unique.join(", ")} } from '${moduleSpecifier}';`;
|
|
860
|
+
dtsStatements.push(statement);
|
|
861
|
+
jsValueStatements.push(statement);
|
|
862
|
+
}
|
|
863
|
+
return { dtsStatements, jsValueStatements };
|
|
864
|
+
};
|
|
331
865
|
const moduleNamespacePath = (namespace) => {
|
|
332
866
|
return namespace.length > 0 ? namespace : "index";
|
|
333
867
|
};
|
|
@@ -512,27 +1046,64 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
|
|
|
512
1046
|
const wrapperImportsByLocalName = new Map();
|
|
513
1047
|
const typeImportsByLocalName = new Map();
|
|
514
1048
|
const typeAliasesByName = new Map();
|
|
1049
|
+
const exportedTypeDeclarationNames = new Set();
|
|
515
1050
|
const exportedFunctionSignaturesByName = new Map();
|
|
1051
|
+
const exportedValueTypesByName = new Map();
|
|
516
1052
|
const memberTypesByClassAndMember = new Map();
|
|
1053
|
+
const anonymousTypeLiteralsByShape = new Map();
|
|
517
1054
|
const printTypeParametersText = (typeParameters) => {
|
|
518
1055
|
if (!typeParameters || typeParameters.length === 0)
|
|
519
1056
|
return "";
|
|
520
1057
|
return `<${typeParameters.map((tp) => tp.getText(sourceFile)).join(", ")}>`;
|
|
521
1058
|
};
|
|
522
|
-
const
|
|
1059
|
+
const printParameterSignature = (param) => {
|
|
523
1060
|
const rest = param.dotDotDotToken ? "..." : "";
|
|
524
1061
|
const name = param.name.getText(sourceFile);
|
|
525
1062
|
const optional = param.questionToken ? "?" : "";
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
:
|
|
529
|
-
|
|
1063
|
+
return {
|
|
1064
|
+
prefixText: `${rest}${name}${optional}: `,
|
|
1065
|
+
typeText: param.type
|
|
1066
|
+
? printTypeNodeText(param.type, sourceFile)
|
|
1067
|
+
: "unknown",
|
|
1068
|
+
};
|
|
530
1069
|
};
|
|
531
1070
|
const addExportedFunctionSignature = (name, signature) => {
|
|
532
1071
|
const signatures = exportedFunctionSignaturesByName.get(name) ?? [];
|
|
533
1072
|
signatures.push(signature);
|
|
534
1073
|
exportedFunctionSignaturesByName.set(name, signatures);
|
|
535
1074
|
};
|
|
1075
|
+
const registerAnonymousTypeLiteralsInTypeNode = (typeNode) => {
|
|
1076
|
+
if (!typeNode)
|
|
1077
|
+
return;
|
|
1078
|
+
const visit = (current) => {
|
|
1079
|
+
if (ts.isTypeLiteralNode(current)) {
|
|
1080
|
+
const shape = renderSourceTypeNodeForAliasLookup(current, new Map());
|
|
1081
|
+
if (!anonymousTypeLiteralsByShape.has(shape)) {
|
|
1082
|
+
const members = new Map();
|
|
1083
|
+
for (const member of current.members) {
|
|
1084
|
+
if (!ts.isPropertySignature(member))
|
|
1085
|
+
continue;
|
|
1086
|
+
if (!member.name || !member.type)
|
|
1087
|
+
continue;
|
|
1088
|
+
const memberName = getPropertyNameText(member.name);
|
|
1089
|
+
if (!memberName)
|
|
1090
|
+
continue;
|
|
1091
|
+
members.set(memberName, {
|
|
1092
|
+
typeNode: member.type,
|
|
1093
|
+
typeText: printTypeNodeText(member.type, sourceFile),
|
|
1094
|
+
isOptional: member.questionToken !== undefined,
|
|
1095
|
+
});
|
|
1096
|
+
}
|
|
1097
|
+
anonymousTypeLiteralsByShape.set(shape, {
|
|
1098
|
+
typeText: printTypeNodeText(current, sourceFile),
|
|
1099
|
+
members,
|
|
1100
|
+
});
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
ts.forEachChild(current, visit);
|
|
1104
|
+
};
|
|
1105
|
+
visit(typeNode);
|
|
1106
|
+
};
|
|
536
1107
|
for (const stmt of sourceFile.statements) {
|
|
537
1108
|
if (ts.isImportDeclaration(stmt)) {
|
|
538
1109
|
const moduleSpecifier = ts.isStringLiteral(stmt.moduleSpecifier)
|
|
@@ -549,9 +1120,6 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
|
|
|
549
1120
|
for (const spec of namedBindings.elements) {
|
|
550
1121
|
const localName = spec.name.text;
|
|
551
1122
|
const importedName = (spec.propertyName ?? spec.name).text;
|
|
552
|
-
const isTypeOnly = clause.isTypeOnly || spec.isTypeOnly;
|
|
553
|
-
if (!isTypeOnly)
|
|
554
|
-
continue;
|
|
555
1123
|
typeImportsByLocalName.set(localName, {
|
|
556
1124
|
source: moduleSpecifier,
|
|
557
1125
|
importedName,
|
|
@@ -567,6 +1135,7 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
|
|
|
567
1135
|
}
|
|
568
1136
|
if (ts.isTypeAliasDeclaration(stmt)) {
|
|
569
1137
|
const aliasName = stmt.name.text;
|
|
1138
|
+
const hasExport = stmt.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
|
|
570
1139
|
const typeParameterNames = (stmt.typeParameters ?? []).map((tp) => tp.name.text);
|
|
571
1140
|
typeAliasesByName.set(aliasName, {
|
|
572
1141
|
typeParametersText: printTypeParametersText(stmt.typeParameters),
|
|
@@ -574,16 +1143,25 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
|
|
|
574
1143
|
type: stmt.type,
|
|
575
1144
|
typeText: printTypeNodeText(stmt.type, sourceFile),
|
|
576
1145
|
});
|
|
1146
|
+
registerAnonymousTypeLiteralsInTypeNode(stmt.type);
|
|
1147
|
+
if (hasExport) {
|
|
1148
|
+
exportedTypeDeclarationNames.add(aliasName);
|
|
1149
|
+
}
|
|
577
1150
|
continue;
|
|
578
1151
|
}
|
|
579
1152
|
if (ts.isFunctionDeclaration(stmt)) {
|
|
580
1153
|
const hasExport = stmt.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
|
|
581
1154
|
if (!hasExport || !stmt.name || !stmt.type)
|
|
582
1155
|
continue;
|
|
583
|
-
const
|
|
1156
|
+
for (const parameter of stmt.parameters) {
|
|
1157
|
+
registerAnonymousTypeLiteralsInTypeNode(parameter.type);
|
|
1158
|
+
}
|
|
1159
|
+
registerAnonymousTypeLiteralsInTypeNode(stmt.type);
|
|
1160
|
+
const parameters = stmt.parameters.map(printParameterSignature);
|
|
584
1161
|
addExportedFunctionSignature(stmt.name.text, {
|
|
585
1162
|
typeParametersText: printTypeParametersText(stmt.typeParameters),
|
|
586
|
-
|
|
1163
|
+
typeParameterCount: stmt.typeParameters?.length ?? 0,
|
|
1164
|
+
parameters,
|
|
587
1165
|
returnTypeText: printTypeNodeText(stmt.type, sourceFile),
|
|
588
1166
|
});
|
|
589
1167
|
continue;
|
|
@@ -601,16 +1179,25 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
|
|
|
601
1179
|
continue;
|
|
602
1180
|
if (!ts.isArrowFunction(initializer) &&
|
|
603
1181
|
!ts.isFunctionExpression(initializer)) {
|
|
1182
|
+
if (declaration.type) {
|
|
1183
|
+
registerAnonymousTypeLiteralsInTypeNode(declaration.type);
|
|
1184
|
+
exportedValueTypesByName.set(exportName, {
|
|
1185
|
+
typeText: printTypeNodeText(declaration.type, sourceFile),
|
|
1186
|
+
});
|
|
1187
|
+
}
|
|
604
1188
|
continue;
|
|
605
1189
|
}
|
|
606
1190
|
if (!initializer.type)
|
|
607
1191
|
continue;
|
|
608
|
-
const
|
|
609
|
-
.
|
|
610
|
-
|
|
1192
|
+
for (const parameter of initializer.parameters) {
|
|
1193
|
+
registerAnonymousTypeLiteralsInTypeNode(parameter.type);
|
|
1194
|
+
}
|
|
1195
|
+
registerAnonymousTypeLiteralsInTypeNode(initializer.type);
|
|
1196
|
+
const parameters = initializer.parameters.map(printParameterSignature);
|
|
611
1197
|
addExportedFunctionSignature(exportName, {
|
|
612
1198
|
typeParametersText: printTypeParametersText(initializer.typeParameters),
|
|
613
|
-
|
|
1199
|
+
typeParameterCount: initializer.typeParameters?.length ?? 0,
|
|
1200
|
+
parameters,
|
|
614
1201
|
returnTypeText: printTypeNodeText(initializer.type, sourceFile),
|
|
615
1202
|
});
|
|
616
1203
|
}
|
|
@@ -618,6 +1205,10 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
|
|
|
618
1205
|
}
|
|
619
1206
|
if (ts.isClassDeclaration(stmt) && stmt.name) {
|
|
620
1207
|
const className = stmt.name.text;
|
|
1208
|
+
const hasExport = stmt.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
|
|
1209
|
+
if (hasExport) {
|
|
1210
|
+
exportedTypeDeclarationNames.add(className);
|
|
1211
|
+
}
|
|
621
1212
|
const members = memberTypesByClassAndMember.get(className) ??
|
|
622
1213
|
new Map();
|
|
623
1214
|
for (const member of stmt.members) {
|
|
@@ -640,6 +1231,7 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
|
|
|
640
1231
|
const name = getPropertyNameText(member.name);
|
|
641
1232
|
if (!name)
|
|
642
1233
|
continue;
|
|
1234
|
+
registerAnonymousTypeLiteralsInTypeNode(member.type);
|
|
643
1235
|
members.set(name, {
|
|
644
1236
|
typeNode: member.type,
|
|
645
1237
|
typeText: printTypeNodeText(member.type, sourceFile),
|
|
@@ -654,6 +1246,10 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
|
|
|
654
1246
|
}
|
|
655
1247
|
if (ts.isInterfaceDeclaration(stmt)) {
|
|
656
1248
|
const interfaceName = stmt.name.text;
|
|
1249
|
+
const hasExport = stmt.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
|
|
1250
|
+
if (hasExport) {
|
|
1251
|
+
exportedTypeDeclarationNames.add(interfaceName);
|
|
1252
|
+
}
|
|
657
1253
|
const members = memberTypesByClassAndMember.get(interfaceName) ??
|
|
658
1254
|
new Map();
|
|
659
1255
|
for (const member of stmt.members) {
|
|
@@ -664,6 +1260,7 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
|
|
|
664
1260
|
const name = getPropertyNameText(member.name);
|
|
665
1261
|
if (!name)
|
|
666
1262
|
continue;
|
|
1263
|
+
registerAnonymousTypeLiteralsInTypeNode(member.type);
|
|
667
1264
|
members.set(name, {
|
|
668
1265
|
typeNode: member.type,
|
|
669
1266
|
typeText: printTypeNodeText(member.type, sourceFile),
|
|
@@ -673,6 +1270,13 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
|
|
|
673
1270
|
if (members.size > 0) {
|
|
674
1271
|
memberTypesByClassAndMember.set(interfaceName, members);
|
|
675
1272
|
}
|
|
1273
|
+
continue;
|
|
1274
|
+
}
|
|
1275
|
+
if (ts.isEnumDeclaration(stmt)) {
|
|
1276
|
+
const hasExport = stmt.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
|
|
1277
|
+
if (hasExport) {
|
|
1278
|
+
exportedTypeDeclarationNames.add(stmt.name.text);
|
|
1279
|
+
}
|
|
676
1280
|
}
|
|
677
1281
|
}
|
|
678
1282
|
return {
|
|
@@ -682,8 +1286,11 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
|
|
|
682
1286
|
wrapperImportsByLocalName,
|
|
683
1287
|
typeImportsByLocalName,
|
|
684
1288
|
typeAliasesByName,
|
|
1289
|
+
exportedTypeDeclarationNames,
|
|
685
1290
|
exportedFunctionSignaturesByName,
|
|
1291
|
+
exportedValueTypesByName,
|
|
686
1292
|
memberTypesByClassAndMember,
|
|
1293
|
+
anonymousTypeLiteralsByShape,
|
|
687
1294
|
},
|
|
688
1295
|
};
|
|
689
1296
|
};
|
|
@@ -798,42 +1405,6 @@ const collectExtensionWrapperImportsFromSourceType = (opts) => {
|
|
|
798
1405
|
}
|
|
799
1406
|
return { ok: true, value: wrappers };
|
|
800
1407
|
};
|
|
801
|
-
const classifyExportKind = (module, name) => {
|
|
802
|
-
const isNamed = (stmt) => typeof stmt.name === "string";
|
|
803
|
-
const findDecl = () => {
|
|
804
|
-
for (const stmt of module.body) {
|
|
805
|
-
if (!("isExported" in stmt) ||
|
|
806
|
-
stmt.isExported !== true)
|
|
807
|
-
continue;
|
|
808
|
-
if (isNamed(stmt) && stmt.name === name)
|
|
809
|
-
return stmt;
|
|
810
|
-
if (stmt.kind === "variableDeclaration") {
|
|
811
|
-
for (const decl of stmt.declarations) {
|
|
812
|
-
if (decl.name.kind === "identifierPattern" &&
|
|
813
|
-
decl.name.name === name) {
|
|
814
|
-
return stmt;
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
return undefined;
|
|
820
|
-
};
|
|
821
|
-
const decl = findDecl();
|
|
822
|
-
if (!decl)
|
|
823
|
-
return "unknown";
|
|
824
|
-
switch (decl.kind) {
|
|
825
|
-
case "typeAliasDeclaration":
|
|
826
|
-
case "interfaceDeclaration":
|
|
827
|
-
return "type";
|
|
828
|
-
case "classDeclaration":
|
|
829
|
-
case "enumDeclaration":
|
|
830
|
-
case "functionDeclaration":
|
|
831
|
-
case "variableDeclaration":
|
|
832
|
-
return "value";
|
|
833
|
-
default:
|
|
834
|
-
return "unknown";
|
|
835
|
-
}
|
|
836
|
-
};
|
|
837
1408
|
const moduleNamespaceToInternalSpecifier = (namespace) => {
|
|
838
1409
|
const nsPath = moduleNamespacePath(namespace);
|
|
839
1410
|
return `./${nsPath}/internal/index.js`;
|
|
@@ -842,6 +1413,12 @@ const toClrTypeName = (namespace, typeName, arity) => {
|
|
|
842
1413
|
const suffix = arity && arity > 0 ? `\`${arity}` : "";
|
|
843
1414
|
return `${namespace}.${typeName}${suffix}`;
|
|
844
1415
|
};
|
|
1416
|
+
const toBindingTypeAlias = (namespace, typeName, arity) => {
|
|
1417
|
+
const normalizedName = normalizeTypeReferenceName(typeName, arity);
|
|
1418
|
+
return namespace.length > 0
|
|
1419
|
+
? `${namespace}.${normalizedName}`
|
|
1420
|
+
: normalizedName;
|
|
1421
|
+
};
|
|
845
1422
|
const toStableId = (assemblyName, clrName) => {
|
|
846
1423
|
return `${assemblyName}:${clrName}`;
|
|
847
1424
|
};
|
|
@@ -870,7 +1447,111 @@ const isNumericValueType = (name) => {
|
|
|
870
1447
|
name === "System.Byte" ||
|
|
871
1448
|
name === "System.SByte");
|
|
872
1449
|
};
|
|
873
|
-
const
|
|
1450
|
+
const rewriteBindingSemanticParameter = (parameter, localTypeNameRemaps) => ({
|
|
1451
|
+
...parameter,
|
|
1452
|
+
type: rewriteBindingSemanticType(parameter.type, localTypeNameRemaps),
|
|
1453
|
+
});
|
|
1454
|
+
const rewriteBindingSemanticMember = (member, localTypeNameRemaps) => {
|
|
1455
|
+
if (member.kind === "propertySignature") {
|
|
1456
|
+
return {
|
|
1457
|
+
...member,
|
|
1458
|
+
type: rewriteBindingSemanticType(member.type, localTypeNameRemaps) ??
|
|
1459
|
+
member.type,
|
|
1460
|
+
};
|
|
1461
|
+
}
|
|
1462
|
+
return {
|
|
1463
|
+
...member,
|
|
1464
|
+
parameters: member.parameters.map((parameter) => rewriteBindingSemanticParameter(parameter, localTypeNameRemaps)),
|
|
1465
|
+
returnType: rewriteBindingSemanticType(member.returnType, localTypeNameRemaps) ??
|
|
1466
|
+
member.returnType,
|
|
1467
|
+
};
|
|
1468
|
+
};
|
|
1469
|
+
const rewriteBindingSemanticType = (type, localTypeNameRemaps) => {
|
|
1470
|
+
if (!type)
|
|
1471
|
+
return undefined;
|
|
1472
|
+
switch (type.kind) {
|
|
1473
|
+
case "referenceType": {
|
|
1474
|
+
const rewrittenName = normalizeTypeReferenceName(localTypeNameRemaps.get(type.name) ?? type.name, type.typeArguments?.length);
|
|
1475
|
+
return {
|
|
1476
|
+
...type,
|
|
1477
|
+
name: rewrittenName,
|
|
1478
|
+
typeArguments: type.typeArguments?.map((arg) => rewriteBindingSemanticType(arg, localTypeNameRemaps)),
|
|
1479
|
+
structuralMembers: type.structuralMembers?.map((member) => rewriteBindingSemanticMember(member, localTypeNameRemaps)),
|
|
1480
|
+
};
|
|
1481
|
+
}
|
|
1482
|
+
case "arrayType":
|
|
1483
|
+
return {
|
|
1484
|
+
...type,
|
|
1485
|
+
elementType: rewriteBindingSemanticType(type.elementType, localTypeNameRemaps) ??
|
|
1486
|
+
type.elementType,
|
|
1487
|
+
};
|
|
1488
|
+
case "tupleType":
|
|
1489
|
+
return {
|
|
1490
|
+
...type,
|
|
1491
|
+
elementTypes: type.elementTypes.map((elementType) => rewriteBindingSemanticType(elementType, localTypeNameRemaps)),
|
|
1492
|
+
};
|
|
1493
|
+
case "functionType":
|
|
1494
|
+
return {
|
|
1495
|
+
...type,
|
|
1496
|
+
parameters: type.parameters.map((parameter) => rewriteBindingSemanticParameter(parameter, localTypeNameRemaps)),
|
|
1497
|
+
returnType: rewriteBindingSemanticType(type.returnType, localTypeNameRemaps) ??
|
|
1498
|
+
type.returnType,
|
|
1499
|
+
};
|
|
1500
|
+
case "objectType":
|
|
1501
|
+
return {
|
|
1502
|
+
...type,
|
|
1503
|
+
members: type.members.map((member) => rewriteBindingSemanticMember(member, localTypeNameRemaps)),
|
|
1504
|
+
};
|
|
1505
|
+
case "dictionaryType":
|
|
1506
|
+
return {
|
|
1507
|
+
...type,
|
|
1508
|
+
keyType: rewriteBindingSemanticType(type.keyType, localTypeNameRemaps) ??
|
|
1509
|
+
type.keyType,
|
|
1510
|
+
valueType: rewriteBindingSemanticType(type.valueType, localTypeNameRemaps) ??
|
|
1511
|
+
type.valueType,
|
|
1512
|
+
};
|
|
1513
|
+
case "unionType":
|
|
1514
|
+
case "intersectionType":
|
|
1515
|
+
return {
|
|
1516
|
+
...type,
|
|
1517
|
+
types: type.types.map((candidate) => rewriteBindingSemanticType(candidate, localTypeNameRemaps)),
|
|
1518
|
+
};
|
|
1519
|
+
default:
|
|
1520
|
+
return type;
|
|
1521
|
+
}
|
|
1522
|
+
};
|
|
1523
|
+
const buildSemanticSignature = (opts) => {
|
|
1524
|
+
return {
|
|
1525
|
+
typeParameters: opts.typeParameters?.map((typeParameter) => typeParameter.name),
|
|
1526
|
+
parameters: opts.parameters.map((parameter) => rewriteBindingSemanticParameter(parameter, opts.localTypeNameRemaps)),
|
|
1527
|
+
returnType: rewriteBindingSemanticType(opts.returnType, opts.localTypeNameRemaps),
|
|
1528
|
+
};
|
|
1529
|
+
};
|
|
1530
|
+
const buildSemanticSignatureFromFunctionType = (type, localTypeNameRemaps) => ({
|
|
1531
|
+
typeParameters: undefined,
|
|
1532
|
+
parameters: type.parameters.map((parameter) => rewriteBindingSemanticParameter(parameter, localTypeNameRemaps)),
|
|
1533
|
+
returnType: rewriteBindingSemanticType(type.returnType, localTypeNameRemaps),
|
|
1534
|
+
});
|
|
1535
|
+
const resolveFunctionTypeFromValueDeclarator = (declarator) => {
|
|
1536
|
+
if (declarator?.type?.kind === "functionType") {
|
|
1537
|
+
return declarator.type;
|
|
1538
|
+
}
|
|
1539
|
+
const initializerType = declarator?.initializer?.inferredType;
|
|
1540
|
+
if (initializerType?.kind === "functionType") {
|
|
1541
|
+
return initializerType;
|
|
1542
|
+
}
|
|
1543
|
+
return undefined;
|
|
1544
|
+
};
|
|
1545
|
+
const areBindingSemanticSignaturesEqual = (left, right) => JSON.stringify(left ?? null) === JSON.stringify(right ?? null);
|
|
1546
|
+
const areBindingSemanticsEqual = (left, right) => left.kind === right.kind &&
|
|
1547
|
+
left.clrName === right.clrName &&
|
|
1548
|
+
left.declaringClrType === right.declaringClrType &&
|
|
1549
|
+
left.declaringAssemblyName === right.declaringAssemblyName &&
|
|
1550
|
+
left.semanticOptional === right.semanticOptional &&
|
|
1551
|
+
JSON.stringify(left.semanticType ?? null) ===
|
|
1552
|
+
JSON.stringify(right.semanticType ?? null) &&
|
|
1553
|
+
areBindingSemanticSignaturesEqual(left.semanticSignature, right.semanticSignature);
|
|
1554
|
+
const toSignatureType = (type, typeParametersInScope, localTypeNameRemaps = new Map()) => {
|
|
874
1555
|
if (!type)
|
|
875
1556
|
return "System.Object";
|
|
876
1557
|
switch (type.kind) {
|
|
@@ -893,20 +1574,20 @@ const toSignatureType = (type, typeParametersInScope) => {
|
|
|
893
1574
|
case "typeParameterType":
|
|
894
1575
|
return type.name;
|
|
895
1576
|
case "arrayType":
|
|
896
|
-
return `${toSignatureType(type.elementType, typeParametersInScope)}[]`;
|
|
1577
|
+
return `${toSignatureType(type.elementType, typeParametersInScope, localTypeNameRemaps)}[]`;
|
|
897
1578
|
case "tupleType":
|
|
898
1579
|
case "objectType":
|
|
899
1580
|
case "functionType":
|
|
900
1581
|
case "dictionaryType":
|
|
901
1582
|
return "System.Object";
|
|
902
1583
|
case "intersectionType":
|
|
903
|
-
return toSignatureType(type.types[0], typeParametersInScope);
|
|
1584
|
+
return toSignatureType(type.types[0], typeParametersInScope, localTypeNameRemaps);
|
|
904
1585
|
case "unionType": {
|
|
905
1586
|
const nonUndefined = type.types.filter((candidate) => {
|
|
906
1587
|
return !(candidate.kind === "primitiveType" && candidate.name === "undefined");
|
|
907
1588
|
});
|
|
908
1589
|
if (nonUndefined.length === 1 && nonUndefined[0]) {
|
|
909
|
-
const single = toSignatureType(nonUndefined[0], typeParametersInScope);
|
|
1590
|
+
const single = toSignatureType(nonUndefined[0], typeParametersInScope, localTypeNameRemaps);
|
|
910
1591
|
if (isNumericValueType(single)) {
|
|
911
1592
|
return `System.Nullable\`1[[${single}]]`;
|
|
912
1593
|
}
|
|
@@ -917,12 +1598,12 @@ const toSignatureType = (type, typeParametersInScope) => {
|
|
|
917
1598
|
case "referenceType": {
|
|
918
1599
|
if (typeParametersInScope.includes(type.name))
|
|
919
1600
|
return type.name;
|
|
920
|
-
const normalizedName = normalizeTypeReferenceName(type.name, type.typeArguments?.length);
|
|
1601
|
+
const normalizedName = normalizeTypeReferenceName(localTypeNameRemaps.get(type.name) ?? type.name, type.typeArguments?.length);
|
|
921
1602
|
if (!type.typeArguments || type.typeArguments.length === 0) {
|
|
922
1603
|
return normalizedName;
|
|
923
1604
|
}
|
|
924
1605
|
const args = type.typeArguments
|
|
925
|
-
.map((arg) => toSignatureType(arg, typeParametersInScope))
|
|
1606
|
+
.map((arg) => toSignatureType(arg, typeParametersInScope, localTypeNameRemaps))
|
|
926
1607
|
.join(",");
|
|
927
1608
|
return `${normalizedName}[[${args}]]`;
|
|
928
1609
|
}
|
|
@@ -947,13 +1628,19 @@ const makeMethodBinding = (opts) => {
|
|
|
947
1628
|
: undefined)
|
|
948
1629
|
.filter((name) => name !== undefined)));
|
|
949
1630
|
const normalizedSignature = `${opts.methodName}|(${opts.parameters
|
|
950
|
-
.map((parameter) => toSignatureType(parameter.type, typeParameterScope))
|
|
951
|
-
.join(",")}):${toSignatureType(opts.returnType, typeParameterScope)}|static=${opts.isStatic ? "true" : "false"}`;
|
|
1631
|
+
.map((parameter) => toSignatureType(parameter.type, typeParameterScope, opts.localTypeNameRemaps))
|
|
1632
|
+
.join(",")}):${toSignatureType(opts.returnType, typeParameterScope, opts.localTypeNameRemaps)}|static=${opts.isStatic ? "true" : "false"}`;
|
|
952
1633
|
const stableId = `${toStableId(opts.declaringAssemblyName, opts.declaringClrType)}::method:${opts.methodName}|${normalizedSignature}`;
|
|
953
1634
|
return {
|
|
954
1635
|
stableId,
|
|
955
1636
|
clrName: opts.methodName,
|
|
956
1637
|
normalizedSignature,
|
|
1638
|
+
semanticSignature: buildSemanticSignature({
|
|
1639
|
+
typeParameters: opts.typeParameters,
|
|
1640
|
+
parameters: opts.parameters,
|
|
1641
|
+
returnType: opts.returnType,
|
|
1642
|
+
localTypeNameRemaps: opts.localTypeNameRemaps ?? new Map(),
|
|
1643
|
+
}),
|
|
957
1644
|
arity: opts.arity,
|
|
958
1645
|
parameterCount: opts.parameters.length,
|
|
959
1646
|
isStatic: opts.isStatic,
|
|
@@ -967,16 +1654,17 @@ const makeMethodBinding = (opts) => {
|
|
|
967
1654
|
isExtensionMethod: false,
|
|
968
1655
|
};
|
|
969
1656
|
};
|
|
970
|
-
const renderClassInternal = (declaration, namespace, memberOverrides) => {
|
|
1657
|
+
const renderClassInternal = (declaration, namespace, memberOverrides, emittedName = declaration.name, localTypeNameRemaps = new Map(), brandName = declaration.name, bindingAlias = declaration.name) => {
|
|
971
1658
|
const lines = [];
|
|
1659
|
+
const isSyntheticAnonymousStructuralClass = emittedName.startsWith("__Anon_") || brandName.startsWith("__Anon_");
|
|
972
1660
|
const typeParameterScope = (declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name);
|
|
973
1661
|
const typeParameters = printTypeParameters(declaration.typeParameters);
|
|
974
|
-
const markerName = `__tsonic_type_${sanitizeForBrand(namespace)}_${sanitizeForBrand(
|
|
1662
|
+
const markerName = `__tsonic_type_${sanitizeForBrand(namespace)}_${sanitizeForBrand(brandName)}`;
|
|
975
1663
|
const heritageNames = [
|
|
976
1664
|
declaration.superClass
|
|
977
|
-
? renderPortableType(declaration.superClass, typeParameterScope)
|
|
1665
|
+
? renderPortableType(declaration.superClass, typeParameterScope, localTypeNameRemaps)
|
|
978
1666
|
: undefined,
|
|
979
|
-
...declaration.implements.map((implementedType) => renderPortableType(implementedType, typeParameterScope)),
|
|
1667
|
+
...declaration.implements.map((implementedType) => renderPortableType(implementedType, typeParameterScope, localTypeNameRemaps)),
|
|
980
1668
|
]
|
|
981
1669
|
.filter((name) => name !== undefined)
|
|
982
1670
|
.map((name) => name.trim())
|
|
@@ -987,8 +1675,11 @@ const renderClassInternal = (declaration, namespace, memberOverrides) => {
|
|
|
987
1675
|
const extendsClause = heritageNames.length > 0
|
|
988
1676
|
? ` extends ${Array.from(new Set(heritageNames)).join(", ")}`
|
|
989
1677
|
: "";
|
|
990
|
-
lines.push(`export interface ${
|
|
991
|
-
|
|
1678
|
+
lines.push(`export interface ${emittedName}$instance${typeParameters}${extendsClause} {`);
|
|
1679
|
+
if (!isSyntheticAnonymousStructuralClass) {
|
|
1680
|
+
lines.push(` readonly ${markerName}: never;`);
|
|
1681
|
+
}
|
|
1682
|
+
lines.push(renderBindingAliasMarker(namespace, bindingAlias));
|
|
992
1683
|
const instanceMembers = declaration.members.filter((member) => {
|
|
993
1684
|
if (member.kind === "constructorDeclaration")
|
|
994
1685
|
return false;
|
|
@@ -998,7 +1689,7 @@ const renderClassInternal = (declaration, namespace, memberOverrides) => {
|
|
|
998
1689
|
});
|
|
999
1690
|
for (const member of instanceMembers) {
|
|
1000
1691
|
if (member.kind === "methodDeclaration") {
|
|
1001
|
-
lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType)}`);
|
|
1692
|
+
lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType, localTypeNameRemaps)}`);
|
|
1002
1693
|
continue;
|
|
1003
1694
|
}
|
|
1004
1695
|
if (member.kind === "propertyDeclaration") {
|
|
@@ -1010,24 +1701,33 @@ const renderClassInternal = (declaration, namespace, memberOverrides) => {
|
|
|
1010
1701
|
const hasSetter = hasAccessorBody
|
|
1011
1702
|
? member.setterBody !== undefined
|
|
1012
1703
|
: !member.isReadonly;
|
|
1704
|
+
const optionalBySource = memberOverride?.emitOptionalPropertySyntax === true &&
|
|
1705
|
+
memberOverride.isOptional === true &&
|
|
1706
|
+
!member.name.startsWith("__tsonic_type_");
|
|
1707
|
+
const optionalMark = optionalBySource ? "?" : "";
|
|
1013
1708
|
const baseType = (memberOverride?.replaceWithSourceType
|
|
1014
1709
|
? memberOverride.sourceTypeText
|
|
1015
|
-
: undefined) ??
|
|
1710
|
+
: undefined) ??
|
|
1711
|
+
renderPortableType(member.type, typeParameterScope, localTypeNameRemaps);
|
|
1016
1712
|
const wrappedType = applyWrappersToBaseType(baseType, memberOverride?.wrappers ?? []);
|
|
1017
|
-
const memberType = memberOverride?.isOptional === true
|
|
1713
|
+
const memberType = memberOverride?.isOptional === true && !optionalBySource
|
|
1018
1714
|
? ensureUndefinedInType(wrappedType)
|
|
1019
1715
|
: wrappedType;
|
|
1020
1716
|
if (hasGetter && !hasSetter) {
|
|
1021
|
-
lines.push(` readonly ${member.name}: ${memberType};`);
|
|
1717
|
+
lines.push(` readonly ${member.name}${optionalMark}: ${memberType};`);
|
|
1022
1718
|
continue;
|
|
1023
1719
|
}
|
|
1024
|
-
lines.push(` ${member.name}: ${memberType};`);
|
|
1720
|
+
lines.push(` ${member.name}${optionalMark}: ${memberType};`);
|
|
1025
1721
|
}
|
|
1026
1722
|
}
|
|
1027
1723
|
lines.push("}");
|
|
1028
1724
|
lines.push("");
|
|
1029
|
-
|
|
1030
|
-
|
|
1725
|
+
if (isSyntheticAnonymousStructuralClass) {
|
|
1726
|
+
lines.push(`export type ${emittedName}${typeParameters} = ${emittedName}$instance${typeParameters};`);
|
|
1727
|
+
return lines;
|
|
1728
|
+
}
|
|
1729
|
+
lines.push(`export const ${emittedName}: {`);
|
|
1730
|
+
lines.push(` new(...args: unknown[]): ${emittedName}${typeParameters};`);
|
|
1031
1731
|
const staticMembers = declaration.members.filter((member) => {
|
|
1032
1732
|
if (member.kind === "constructorDeclaration")
|
|
1033
1733
|
return false;
|
|
@@ -1035,26 +1735,26 @@ const renderClassInternal = (declaration, namespace, memberOverrides) => {
|
|
|
1035
1735
|
});
|
|
1036
1736
|
for (const member of staticMembers) {
|
|
1037
1737
|
if (member.kind === "methodDeclaration") {
|
|
1038
|
-
lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType)}`);
|
|
1738
|
+
lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType, localTypeNameRemaps)}`);
|
|
1039
1739
|
continue;
|
|
1040
1740
|
}
|
|
1041
1741
|
if (member.kind === "propertyDeclaration") {
|
|
1042
|
-
lines.push(` ${member.name}: ${renderPortableType(member.type)};`);
|
|
1742
|
+
lines.push(` ${member.name}: ${renderPortableType(member.type, typeParameterScope, localTypeNameRemaps)};`);
|
|
1043
1743
|
}
|
|
1044
1744
|
}
|
|
1045
1745
|
lines.push("};");
|
|
1046
1746
|
lines.push("");
|
|
1047
|
-
lines.push(`export type ${
|
|
1747
|
+
lines.push(`export type ${emittedName}${typeParameters} = ${emittedName}$instance${typeParameters};`);
|
|
1048
1748
|
lines.push("");
|
|
1049
1749
|
return lines;
|
|
1050
1750
|
};
|
|
1051
|
-
const renderInterfaceInternal = (declaration, namespace, memberOverrides) => {
|
|
1751
|
+
const renderInterfaceInternal = (declaration, namespace, memberOverrides, emittedName = declaration.name, localTypeNameRemaps = new Map(), brandName = declaration.name, bindingAlias = declaration.name) => {
|
|
1052
1752
|
const lines = [];
|
|
1053
1753
|
const typeParameterScope = (declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name);
|
|
1054
1754
|
const typeParameters = printTypeParameters(declaration.typeParameters);
|
|
1055
|
-
const markerName = `__tsonic_type_${sanitizeForBrand(namespace)}_${sanitizeForBrand(
|
|
1755
|
+
const markerName = `__tsonic_type_${sanitizeForBrand(namespace)}_${sanitizeForBrand(brandName)}`;
|
|
1056
1756
|
const extendsNames = declaration.extends
|
|
1057
|
-
.map((baseType) => renderPortableType(baseType, typeParameterScope).trim())
|
|
1757
|
+
.map((baseType) => renderPortableType(baseType, typeParameterScope, localTypeNameRemaps).trim())
|
|
1058
1758
|
.filter((name) => name.length > 0 &&
|
|
1059
1759
|
name !== "unknown" &&
|
|
1060
1760
|
name !== "never" &&
|
|
@@ -1062,11 +1762,12 @@ const renderInterfaceInternal = (declaration, namespace, memberOverrides) => {
|
|
|
1062
1762
|
const extendsClause = extendsNames.length > 0
|
|
1063
1763
|
? ` extends ${Array.from(new Set(extendsNames)).join(", ")}`
|
|
1064
1764
|
: "";
|
|
1065
|
-
lines.push(`export interface ${
|
|
1765
|
+
lines.push(`export interface ${emittedName}$instance${typeParameters}${extendsClause} {`);
|
|
1066
1766
|
lines.push(` readonly ${markerName}?: never;`);
|
|
1767
|
+
lines.push(renderBindingAliasMarker(namespace, bindingAlias));
|
|
1067
1768
|
for (const member of declaration.members) {
|
|
1068
1769
|
if (member.kind === "methodSignature") {
|
|
1069
|
-
lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType)}`);
|
|
1770
|
+
lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType, localTypeNameRemaps)}`);
|
|
1070
1771
|
continue;
|
|
1071
1772
|
}
|
|
1072
1773
|
if (member.kind === "propertySignature") {
|
|
@@ -1077,7 +1778,8 @@ const renderInterfaceInternal = (declaration, namespace, memberOverrides) => {
|
|
|
1077
1778
|
const optionalMark = optionalBySource || member.isOptional ? "?" : "";
|
|
1078
1779
|
const baseType = (memberOverride?.replaceWithSourceType
|
|
1079
1780
|
? memberOverride.sourceTypeText
|
|
1080
|
-
: undefined) ??
|
|
1781
|
+
: undefined) ??
|
|
1782
|
+
renderPortableType(member.type, typeParameterScope, localTypeNameRemaps);
|
|
1081
1783
|
const wrappedType = applyWrappersToBaseType(baseType, memberOverride?.wrappers ?? []);
|
|
1082
1784
|
const memberType = memberOverride?.isOptional && !optionalBySource
|
|
1083
1785
|
? ensureUndefinedInType(wrappedType)
|
|
@@ -1087,13 +1789,13 @@ const renderInterfaceInternal = (declaration, namespace, memberOverrides) => {
|
|
|
1087
1789
|
}
|
|
1088
1790
|
lines.push("}");
|
|
1089
1791
|
lines.push("");
|
|
1090
|
-
lines.push(`export type ${
|
|
1792
|
+
lines.push(`export type ${emittedName}${typeParameters} = ${emittedName}$instance${typeParameters};`);
|
|
1091
1793
|
lines.push("");
|
|
1092
1794
|
return lines;
|
|
1093
1795
|
};
|
|
1094
|
-
const renderEnumInternal = (declaration) => {
|
|
1796
|
+
const renderEnumInternal = (declaration, emittedName = declaration.name) => {
|
|
1095
1797
|
const lines = [];
|
|
1096
|
-
lines.push(`export enum ${
|
|
1798
|
+
lines.push(`export enum ${emittedName} {`);
|
|
1097
1799
|
declaration.members.forEach((member, index) => {
|
|
1098
1800
|
lines.push(` ${member.name} = ${index},`);
|
|
1099
1801
|
});
|
|
@@ -1101,16 +1803,22 @@ const renderEnumInternal = (declaration) => {
|
|
|
1101
1803
|
lines.push("");
|
|
1102
1804
|
return lines;
|
|
1103
1805
|
};
|
|
1104
|
-
const renderStructuralAliasInternal = (declaration, namespace, memberOverrides)
|
|
1806
|
+
const renderStructuralAliasInternal = (declaration, namespace, memberOverrides, emittedName = declaration.name, localTypeNameRemaps = new Map(), brandAliasName = `${declaration.name}__Alias${(declaration.typeParameters?.length ?? 0) > 0
|
|
1807
|
+
? `_${declaration.typeParameters?.length ?? 0}`
|
|
1808
|
+
: ""}`, bindingAlias = `${declaration.name}__Alias${(declaration.typeParameters?.length ?? 0) > 0
|
|
1809
|
+
? `_${declaration.typeParameters?.length ?? 0}`
|
|
1810
|
+
: ""}`) => {
|
|
1105
1811
|
if (declaration.type.kind !== "objectType")
|
|
1106
1812
|
return [];
|
|
1107
1813
|
const lines = [];
|
|
1108
1814
|
const arity = declaration.typeParameters?.length ?? 0;
|
|
1109
1815
|
const typeParameters = printTypeParameters(declaration.typeParameters);
|
|
1110
|
-
const
|
|
1111
|
-
const
|
|
1816
|
+
const typeParameterScope = (declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name);
|
|
1817
|
+
const internalAliasName = `${emittedName}__Alias${arity > 0 ? `_${arity}` : ""}`;
|
|
1818
|
+
const markerName = `__tsonic_type_${sanitizeForBrand(namespace)}_${sanitizeForBrand(brandAliasName)}`;
|
|
1112
1819
|
lines.push(`export interface ${internalAliasName}$instance${typeParameters} {`);
|
|
1113
1820
|
lines.push(` readonly ${markerName}?: never;`);
|
|
1821
|
+
lines.push(renderBindingAliasMarker(namespace, bindingAlias));
|
|
1114
1822
|
for (const member of declaration.type.members) {
|
|
1115
1823
|
if (member.kind === "methodSignature") {
|
|
1116
1824
|
lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType)}`);
|
|
@@ -1121,7 +1829,8 @@ const renderStructuralAliasInternal = (declaration, namespace, memberOverrides)
|
|
|
1121
1829
|
const optionalMark = member.isOptional ? "?" : "";
|
|
1122
1830
|
const baseType = (memberOverride?.replaceWithSourceType
|
|
1123
1831
|
? memberOverride.sourceTypeText
|
|
1124
|
-
: undefined) ??
|
|
1832
|
+
: undefined) ??
|
|
1833
|
+
renderPortableType(member.type, typeParameterScope, localTypeNameRemaps);
|
|
1125
1834
|
const wrappedType = applyWrappersToBaseType(baseType, memberOverride?.wrappers ?? []);
|
|
1126
1835
|
const memberType = memberOverride?.isOptional === true
|
|
1127
1836
|
? ensureUndefinedInType(wrappedType)
|
|
@@ -1129,20 +1838,73 @@ const renderStructuralAliasInternal = (declaration, namespace, memberOverrides)
|
|
|
1129
1838
|
lines.push(` ${member.name}${optionalMark}: ${memberType};`);
|
|
1130
1839
|
}
|
|
1131
1840
|
}
|
|
1132
|
-
lines.push("}");
|
|
1133
|
-
lines.push("");
|
|
1134
|
-
lines.push(`export type ${internalAliasName}${typeParameters} = ${internalAliasName}$instance${typeParameters};`);
|
|
1135
|
-
lines.push("");
|
|
1136
|
-
return lines;
|
|
1841
|
+
lines.push("}");
|
|
1842
|
+
lines.push("");
|
|
1843
|
+
lines.push(`export type ${internalAliasName}${typeParameters} = ${internalAliasName}$instance${typeParameters};`);
|
|
1844
|
+
lines.push("");
|
|
1845
|
+
return lines;
|
|
1846
|
+
};
|
|
1847
|
+
const renderTypeAliasInternal = (declaration, emittedName = declaration.name, localTypeNameRemaps = new Map(), anonymousStructuralAliases = new Map()) => {
|
|
1848
|
+
if (declaration.type.kind === "objectType")
|
|
1849
|
+
return [];
|
|
1850
|
+
const typeParameterScope = (declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name);
|
|
1851
|
+
const typeParameters = printTypeParameters(declaration.typeParameters);
|
|
1852
|
+
return [
|
|
1853
|
+
`export type ${emittedName}${typeParameters} = ${renderPortableType(declaration.type, typeParameterScope, localTypeNameRemaps, anonymousStructuralAliases)};`,
|
|
1854
|
+
"",
|
|
1855
|
+
];
|
|
1856
|
+
};
|
|
1857
|
+
const renderSourceAliasPlan = (plan, anonymousStructuralAliases) => {
|
|
1858
|
+
const sourceTypeParams = plan.sourceAlias?.typeParametersText ??
|
|
1859
|
+
printTypeParameters(plan.declaration.typeParameters);
|
|
1860
|
+
if (plan.declaration.type.kind === "objectType") {
|
|
1861
|
+
const arity = plan.declaration.typeParameters?.length ?? 0;
|
|
1862
|
+
const internalName = `${plan.declaration.name}__Alias${arity > 0 ? `_${arity}` : ""}`;
|
|
1863
|
+
const typeArgs = plan.sourceAlias && plan.sourceAlias.typeParameterNames.length > 0
|
|
1864
|
+
? `<${plan.sourceAlias.typeParameterNames.join(", ")}>`
|
|
1865
|
+
: plan.declaration.typeParameters &&
|
|
1866
|
+
plan.declaration.typeParameters.length > 0
|
|
1867
|
+
? `<${plan.declaration.typeParameters.map((tp) => tp.name).join(", ")}>`
|
|
1868
|
+
: "";
|
|
1869
|
+
return {
|
|
1870
|
+
line: `export type ${plan.declaration.name}${sourceTypeParams} = ${internalName}${typeArgs};`,
|
|
1871
|
+
internalImport: internalName,
|
|
1872
|
+
};
|
|
1873
|
+
}
|
|
1874
|
+
const rhs = renderPortableType(plan.declaration.type, plan.declaration.typeParameters?.map((tp) => tp.name) ?? [], new Map(), anonymousStructuralAliases);
|
|
1875
|
+
const shouldPreferSourceAliasText = plan.sourceAlias !== undefined &&
|
|
1876
|
+
!typeNodeUsesImportedTypeNames(plan.sourceAlias.type, plan.typeImportsByLocalName) &&
|
|
1877
|
+
/__\d+\b|\$instance\b/.test(rhs);
|
|
1878
|
+
return {
|
|
1879
|
+
line: `export type ${plan.declaration.name}${sourceTypeParams} = ${shouldPreferSourceAliasText
|
|
1880
|
+
? rewriteSourceTypeText(plan.sourceAlias.typeText, new Map(), anonymousStructuralAliases)
|
|
1881
|
+
: rhs};`,
|
|
1882
|
+
};
|
|
1137
1883
|
};
|
|
1138
|
-
const renderContainerInternal = (entry) => {
|
|
1884
|
+
const renderContainerInternal = (entry, anonymousStructuralAliases) => {
|
|
1139
1885
|
const lines = [];
|
|
1140
1886
|
lines.push(`export abstract class ${entry.module.className}$instance {`);
|
|
1141
1887
|
for (const method of entry.methods) {
|
|
1142
|
-
|
|
1888
|
+
const sourceSignature = renderSourceFunctionSignature({
|
|
1889
|
+
declaration: method.declaration,
|
|
1890
|
+
sourceSignatures: method.sourceSignatures,
|
|
1891
|
+
localTypeNameRemaps: method.localTypeNameRemaps,
|
|
1892
|
+
anonymousStructuralAliases,
|
|
1893
|
+
});
|
|
1894
|
+
lines.push(` static ${sourceSignature
|
|
1895
|
+
? `${method.localName}${sourceSignature.typeParametersText}(${sourceSignature.parametersText}): ${sourceSignature.returnTypeText};`
|
|
1896
|
+
: renderMethodSignature(method.localName, method.declaration.typeParameters, method.declaration.parameters, method.declaration.returnType, method.localTypeNameRemaps, anonymousStructuralAliases)}`);
|
|
1143
1897
|
}
|
|
1144
1898
|
for (const variable of entry.variables) {
|
|
1145
|
-
|
|
1899
|
+
const sourceFunctionTypeText = renderSourceFunctionType({
|
|
1900
|
+
sourceSignatures: variable.sourceSignatures,
|
|
1901
|
+
localTypeNameRemaps: variable.localTypeNameRemaps,
|
|
1902
|
+
anonymousStructuralAliases,
|
|
1903
|
+
});
|
|
1904
|
+
const sourceTypeText = sourceFunctionTypeText ??
|
|
1905
|
+
renderSourceValueType(variable.sourceType, variable.localTypeNameRemaps, anonymousStructuralAliases);
|
|
1906
|
+
lines.push(` static ${variable.localName}: ${sourceTypeText ??
|
|
1907
|
+
renderPortableType(variable.declarator?.type, [], variable.localTypeNameRemaps, anonymousStructuralAliases)};`);
|
|
1146
1908
|
}
|
|
1147
1909
|
lines.push("}");
|
|
1148
1910
|
lines.push("");
|
|
@@ -1150,7 +1912,7 @@ const renderContainerInternal = (entry) => {
|
|
|
1150
1912
|
lines.push("");
|
|
1151
1913
|
return lines;
|
|
1152
1914
|
};
|
|
1153
|
-
const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
|
|
1915
|
+
const buildTypeBindingFromClass = (declaration, namespace, assemblyName, localTypeNameRemaps = new Map()) => {
|
|
1154
1916
|
const declaringClrType = toClrTypeName(namespace, declaration.name, declaration.typeParameters?.length ?? 0);
|
|
1155
1917
|
const typeStableId = toStableId(assemblyName, declaringClrType);
|
|
1156
1918
|
const typeParameterScope = declaration.typeParameters?.map((typeParameter) => typeParameter.name) ??
|
|
@@ -1162,7 +1924,7 @@ const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
|
|
|
1162
1924
|
if (member.kind === "constructorDeclaration") {
|
|
1163
1925
|
constructors.push({
|
|
1164
1926
|
normalizedSignature: `.ctor|(${member.parameters
|
|
1165
|
-
.map((parameter) => toSignatureType(parameter.type, typeParameterScope))
|
|
1927
|
+
.map((parameter) => toSignatureType(parameter.type, typeParameterScope, localTypeNameRemaps))
|
|
1166
1928
|
.join(",")})|static=false`,
|
|
1167
1929
|
isStatic: false,
|
|
1168
1930
|
parameterCount: member.parameters.length,
|
|
@@ -1176,12 +1938,14 @@ const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
|
|
|
1176
1938
|
methodName: member.name,
|
|
1177
1939
|
parameters: member.parameters,
|
|
1178
1940
|
returnType: member.returnType,
|
|
1941
|
+
typeParameters: member.typeParameters,
|
|
1179
1942
|
arity: member.typeParameters?.length ?? 0,
|
|
1180
1943
|
parameterModifiers: buildParameterModifiers(member.parameters),
|
|
1181
1944
|
isStatic: member.isStatic,
|
|
1182
1945
|
isAbstract: member.body === undefined,
|
|
1183
1946
|
isVirtual: member.isVirtual,
|
|
1184
1947
|
isOverride: member.isOverride,
|
|
1948
|
+
localTypeNameRemaps,
|
|
1185
1949
|
}));
|
|
1186
1950
|
continue;
|
|
1187
1951
|
}
|
|
@@ -1193,11 +1957,12 @@ const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
|
|
|
1193
1957
|
const hasSetter = hasAccessorBody
|
|
1194
1958
|
? member.setterBody !== undefined
|
|
1195
1959
|
: !member.isReadonly;
|
|
1196
|
-
const propertyType = toSignatureType(member.type, typeParameterScope);
|
|
1960
|
+
const propertyType = toSignatureType(member.type, typeParameterScope, localTypeNameRemaps);
|
|
1197
1961
|
properties.push({
|
|
1198
1962
|
stableId: `${typeStableId}::property:${member.name}`,
|
|
1199
1963
|
clrName: member.name,
|
|
1200
1964
|
normalizedSignature: `${member.name}|:${propertyType}|static=${member.isStatic ? "true" : "false"}|accessor=${hasGetter && hasSetter ? "getset" : hasSetter ? "set" : "get"}`,
|
|
1965
|
+
semanticType: rewriteBindingSemanticType(member.type, localTypeNameRemaps),
|
|
1201
1966
|
isStatic: member.isStatic,
|
|
1202
1967
|
isAbstract: member.getterBody === undefined && member.setterBody === undefined
|
|
1203
1968
|
? false
|
|
@@ -1215,6 +1980,7 @@ const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
|
|
|
1215
1980
|
return {
|
|
1216
1981
|
stableId: typeStableId,
|
|
1217
1982
|
clrName: declaringClrType,
|
|
1983
|
+
alias: toBindingTypeAlias(namespace, declaration.name, declaration.typeParameters?.length ?? 0),
|
|
1218
1984
|
assemblyName,
|
|
1219
1985
|
kind: declaration.isStruct ? "Struct" : "Class",
|
|
1220
1986
|
accessibility: "Public",
|
|
@@ -1239,7 +2005,7 @@ const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
|
|
|
1239
2005
|
],
|
|
1240
2006
|
};
|
|
1241
2007
|
};
|
|
1242
|
-
const buildTypeBindingFromInterface = (declaration, namespace, assemblyName) => {
|
|
2008
|
+
const buildTypeBindingFromInterface = (declaration, namespace, assemblyName, localTypeNameRemaps = new Map()) => {
|
|
1243
2009
|
const declaringClrType = toClrTypeName(namespace, declaration.name, declaration.typeParameters?.length ?? 0);
|
|
1244
2010
|
const typeStableId = toStableId(assemblyName, declaringClrType);
|
|
1245
2011
|
const typeParameterScope = declaration.typeParameters?.map((typeParameter) => typeParameter.name) ??
|
|
@@ -1254,17 +2020,21 @@ const buildTypeBindingFromInterface = (declaration, namespace, assemblyName) =>
|
|
|
1254
2020
|
methodName: member.name,
|
|
1255
2021
|
parameters: member.parameters,
|
|
1256
2022
|
returnType: member.returnType,
|
|
2023
|
+
typeParameters: member.typeParameters,
|
|
1257
2024
|
arity: member.typeParameters?.length ?? 0,
|
|
1258
2025
|
parameterModifiers: buildParameterModifiers(member.parameters),
|
|
1259
2026
|
isStatic: false,
|
|
1260
2027
|
isAbstract: true,
|
|
2028
|
+
localTypeNameRemaps,
|
|
1261
2029
|
}));
|
|
1262
2030
|
continue;
|
|
1263
2031
|
}
|
|
1264
2032
|
properties.push({
|
|
1265
2033
|
stableId: `${typeStableId}::property:${member.name}`,
|
|
1266
2034
|
clrName: member.name,
|
|
1267
|
-
normalizedSignature: `${member.name}|:${toSignatureType(member.type, typeParameterScope)}|static=false|accessor=${member.isReadonly ? "get" : "getset"}`,
|
|
2035
|
+
normalizedSignature: `${member.name}|:${toSignatureType(member.type, typeParameterScope, localTypeNameRemaps)}|static=false|accessor=${member.isReadonly ? "get" : "getset"}`,
|
|
2036
|
+
semanticType: rewriteBindingSemanticType(member.type, localTypeNameRemaps),
|
|
2037
|
+
semanticOptional: member.isOptional,
|
|
1268
2038
|
isStatic: false,
|
|
1269
2039
|
isAbstract: true,
|
|
1270
2040
|
isVirtual: false,
|
|
@@ -1279,6 +2049,7 @@ const buildTypeBindingFromInterface = (declaration, namespace, assemblyName) =>
|
|
|
1279
2049
|
return {
|
|
1280
2050
|
stableId: typeStableId,
|
|
1281
2051
|
clrName: declaringClrType,
|
|
2052
|
+
alias: toBindingTypeAlias(namespace, declaration.name, declaration.typeParameters?.length ?? 0),
|
|
1282
2053
|
assemblyName,
|
|
1283
2054
|
kind: declaration.isStruct ? "Struct" : "Interface",
|
|
1284
2055
|
accessibility: "Public",
|
|
@@ -1311,6 +2082,7 @@ const buildTypeBindingFromEnum = (declaration, namespace, assemblyName) => {
|
|
|
1311
2082
|
return {
|
|
1312
2083
|
stableId: typeStableId,
|
|
1313
2084
|
clrName: declaringClrType,
|
|
2085
|
+
alias: toBindingTypeAlias(namespace, declaration.name),
|
|
1314
2086
|
assemblyName,
|
|
1315
2087
|
kind: "Enum",
|
|
1316
2088
|
accessibility: "Public",
|
|
@@ -1326,7 +2098,7 @@ const buildTypeBindingFromEnum = (declaration, namespace, assemblyName) => {
|
|
|
1326
2098
|
constructors: [],
|
|
1327
2099
|
};
|
|
1328
2100
|
};
|
|
1329
|
-
const buildTypeBindingFromStructuralAlias = (declaration, namespace, assemblyName) => {
|
|
2101
|
+
const buildTypeBindingFromStructuralAlias = (declaration, namespace, assemblyName, localTypeNameRemaps = new Map()) => {
|
|
1330
2102
|
if (declaration.type.kind !== "objectType")
|
|
1331
2103
|
return undefined;
|
|
1332
2104
|
const arity = declaration.typeParameters?.length ?? 0;
|
|
@@ -1345,17 +2117,21 @@ const buildTypeBindingFromStructuralAlias = (declaration, namespace, assemblyNam
|
|
|
1345
2117
|
methodName: member.name,
|
|
1346
2118
|
parameters: member.parameters,
|
|
1347
2119
|
returnType: member.returnType,
|
|
2120
|
+
typeParameters: member.typeParameters,
|
|
1348
2121
|
arity: member.typeParameters?.length ?? 0,
|
|
1349
2122
|
parameterModifiers: buildParameterModifiers(member.parameters),
|
|
1350
2123
|
isStatic: false,
|
|
1351
2124
|
isAbstract: true,
|
|
2125
|
+
localTypeNameRemaps,
|
|
1352
2126
|
}));
|
|
1353
2127
|
continue;
|
|
1354
2128
|
}
|
|
1355
2129
|
properties.push({
|
|
1356
2130
|
stableId: `${typeStableId}::property:${member.name}`,
|
|
1357
2131
|
clrName: member.name,
|
|
1358
|
-
normalizedSignature: `${member.name}|:${toSignatureType(member.type, typeParameterScope)}|static=false|accessor=${member.isReadonly ? "get" : "getset"}`,
|
|
2132
|
+
normalizedSignature: `${member.name}|:${toSignatureType(member.type, typeParameterScope, localTypeNameRemaps)}|static=false|accessor=${member.isReadonly ? "get" : "getset"}`,
|
|
2133
|
+
semanticType: rewriteBindingSemanticType(member.type, localTypeNameRemaps),
|
|
2134
|
+
semanticOptional: member.isOptional,
|
|
1359
2135
|
isStatic: false,
|
|
1360
2136
|
isAbstract: true,
|
|
1361
2137
|
isVirtual: false,
|
|
@@ -1370,6 +2146,7 @@ const buildTypeBindingFromStructuralAlias = (declaration, namespace, assemblyNam
|
|
|
1370
2146
|
return {
|
|
1371
2147
|
stableId: typeStableId,
|
|
1372
2148
|
clrName: declaringClrType,
|
|
2149
|
+
alias: toBindingTypeAlias(namespace, internalAliasName, arity),
|
|
1373
2150
|
assemblyName,
|
|
1374
2151
|
kind: declaration.isStruct ? "Struct" : "Class",
|
|
1375
2152
|
accessibility: "Public",
|
|
@@ -1398,11 +2175,13 @@ const buildTypeBindingFromContainer = (entry, namespace, assemblyName) => {
|
|
|
1398
2175
|
arity: method.declaration.typeParameters?.length ?? 0,
|
|
1399
2176
|
parameterModifiers: buildParameterModifiers(method.declaration.parameters),
|
|
1400
2177
|
isStatic: true,
|
|
2178
|
+
localTypeNameRemaps: method.localTypeNameRemaps,
|
|
1401
2179
|
}));
|
|
1402
2180
|
const properties = entry.variables.map((variable) => ({
|
|
1403
2181
|
stableId: `${typeStableId}::property:${variable.localName}`,
|
|
1404
2182
|
clrName: variable.localName,
|
|
1405
|
-
normalizedSignature: `${variable.localName}|:${toSignatureType(variable.declarator?.type, [])}|static=true|accessor=getset`,
|
|
2183
|
+
normalizedSignature: `${variable.localName}|:${toSignatureType(variable.declarator?.type, [], variable.localTypeNameRemaps)}|static=true|accessor=getset`,
|
|
2184
|
+
semanticType: rewriteBindingSemanticType(variable.declarator?.type, variable.localTypeNameRemaps),
|
|
1406
2185
|
isStatic: true,
|
|
1407
2186
|
isAbstract: false,
|
|
1408
2187
|
isVirtual: false,
|
|
@@ -1416,6 +2195,7 @@ const buildTypeBindingFromContainer = (entry, namespace, assemblyName) => {
|
|
|
1416
2195
|
return {
|
|
1417
2196
|
stableId: typeStableId,
|
|
1418
2197
|
clrName: declaringClrType,
|
|
2198
|
+
alias: toBindingTypeAlias(namespace, entry.module.className),
|
|
1419
2199
|
assemblyName,
|
|
1420
2200
|
kind: "Class",
|
|
1421
2201
|
accessibility: "Public",
|
|
@@ -1451,37 +2231,112 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1451
2231
|
for (const [namespace, moduleList] of Array.from(modulesByNamespace.entries())) {
|
|
1452
2232
|
const typeDeclarations = [];
|
|
1453
2233
|
const moduleContainers = [];
|
|
2234
|
+
const crossNamespaceReexportsGrouped = new Map();
|
|
2235
|
+
const crossNamespaceTypeDeclarations = [];
|
|
2236
|
+
const seenCrossNamespaceTypeDeclarationKeys = new Set();
|
|
1454
2237
|
const valueExportsMap = new Map();
|
|
1455
2238
|
const seenTypeDeclarationKeys = new Set();
|
|
1456
|
-
const
|
|
1457
|
-
const sourceAliasInternalImports = new Set();
|
|
2239
|
+
const sourceAliasPlans = [];
|
|
1458
2240
|
const memberOverrides = [];
|
|
2241
|
+
const internalTypeImportByAlias = new Map();
|
|
2242
|
+
const facadeTypeImportByAlias = new Map();
|
|
1459
2243
|
const wrapperImportByAlias = new Map();
|
|
2244
|
+
const internalHelperTypeDeclarationsByKey = new Map();
|
|
2245
|
+
const internalHelperTypeRemapsByModuleKey = new Map();
|
|
2246
|
+
const getInternalHelperTypeName = (moduleFileKey, localName) => {
|
|
2247
|
+
return `__Local_${sanitizeForBrand(moduleFileKey)}_${sanitizeForBrand(localName)}`;
|
|
2248
|
+
};
|
|
2249
|
+
const registerInternalHelperTypeClosure = (opts) => {
|
|
2250
|
+
if (!opts.sourceIndex)
|
|
2251
|
+
return { ok: true, value: new Map() };
|
|
2252
|
+
const moduleFileKey = normalizeModuleFileKey(opts.declarationModule.filePath);
|
|
2253
|
+
const remaps = internalHelperTypeRemapsByModuleKey.get(moduleFileKey) ?? new Map();
|
|
2254
|
+
if (!internalHelperTypeRemapsByModuleKey.has(moduleFileKey)) {
|
|
2255
|
+
internalHelperTypeRemapsByModuleKey.set(moduleFileKey, remaps);
|
|
2256
|
+
}
|
|
2257
|
+
const visiting = new Set();
|
|
2258
|
+
const visitLocalType = (localName) => {
|
|
2259
|
+
if (opts.sourceIndex?.exportedTypeDeclarationNames.has(localName)) {
|
|
2260
|
+
return { ok: true, value: undefined };
|
|
2261
|
+
}
|
|
2262
|
+
const declaration = resolveModuleLocalDeclaration(opts.declarationModule, localName);
|
|
2263
|
+
if (!declaration)
|
|
2264
|
+
return { ok: true, value: undefined };
|
|
2265
|
+
const kind = classifyLocalTypeDeclarationKind(declaration);
|
|
2266
|
+
if (!kind)
|
|
2267
|
+
return { ok: true, value: undefined };
|
|
2268
|
+
const localTypeDeclaration = declaration;
|
|
2269
|
+
const key = `${moduleFileKey}::${localName}`;
|
|
2270
|
+
if (!remaps.has(localName)) {
|
|
2271
|
+
remaps.set(localName, getInternalHelperTypeName(moduleFileKey, localName));
|
|
2272
|
+
}
|
|
2273
|
+
if (internalHelperTypeDeclarationsByKey.has(key)) {
|
|
2274
|
+
return { ok: true, value: undefined };
|
|
2275
|
+
}
|
|
2276
|
+
if (visiting.has(key))
|
|
2277
|
+
return { ok: true, value: undefined };
|
|
2278
|
+
visiting.add(key);
|
|
2279
|
+
const nestedReferencedNames = new Set();
|
|
2280
|
+
collectReferencedPortableTypeNamesFromDeclaration(localTypeDeclaration, nestedReferencedNames);
|
|
2281
|
+
for (const nestedName of nestedReferencedNames) {
|
|
2282
|
+
const visited = visitLocalType(nestedName);
|
|
2283
|
+
if (!visited.ok)
|
|
2284
|
+
return visited;
|
|
2285
|
+
}
|
|
2286
|
+
visiting.delete(key);
|
|
2287
|
+
const emittedName = remaps.get(localName);
|
|
2288
|
+
if (!emittedName) {
|
|
2289
|
+
return {
|
|
2290
|
+
ok: false,
|
|
2291
|
+
error: `Internal error: missing emitted name remap for local helper '${localName}'.`,
|
|
2292
|
+
};
|
|
2293
|
+
}
|
|
2294
|
+
internalHelperTypeDeclarationsByKey.set(key, {
|
|
2295
|
+
key,
|
|
2296
|
+
moduleFileKey,
|
|
2297
|
+
declaringNamespace: opts.declarationModule.namespace,
|
|
2298
|
+
emittedName,
|
|
2299
|
+
originalName: localName,
|
|
2300
|
+
kind,
|
|
2301
|
+
declaration: localTypeDeclaration,
|
|
2302
|
+
});
|
|
2303
|
+
return { ok: true, value: undefined };
|
|
2304
|
+
};
|
|
2305
|
+
for (const referencedName of opts.referencedNames) {
|
|
2306
|
+
const visited = visitLocalType(referencedName);
|
|
2307
|
+
if (!visited.ok)
|
|
2308
|
+
return visited;
|
|
2309
|
+
}
|
|
2310
|
+
return { ok: true, value: new Map(remaps) };
|
|
2311
|
+
};
|
|
1460
2312
|
const registerValueExport = (valueExport) => {
|
|
1461
2313
|
const existing = valueExportsMap.get(valueExport.exportName);
|
|
1462
2314
|
if (!existing) {
|
|
1463
2315
|
valueExportsMap.set(valueExport.exportName, valueExport);
|
|
1464
2316
|
return { ok: true, value: undefined };
|
|
1465
2317
|
}
|
|
1466
|
-
const sameBinding = existing.binding
|
|
1467
|
-
existing.binding.clrName === valueExport.binding.clrName &&
|
|
1468
|
-
existing.binding.declaringClrType ===
|
|
1469
|
-
valueExport.binding.declaringClrType &&
|
|
1470
|
-
existing.binding.declaringAssemblyName ===
|
|
1471
|
-
valueExport.binding.declaringAssemblyName;
|
|
2318
|
+
const sameBinding = areBindingSemanticsEqual(existing.binding, valueExport.binding);
|
|
1472
2319
|
const normalizeFunctionFacade = (facade) => {
|
|
1473
2320
|
const declaration = facade.declaration;
|
|
1474
2321
|
const typeParametersText = printTypeParameters(declaration.typeParameters);
|
|
1475
2322
|
const typeParameterNames = declaration.typeParameters?.map((typeParameter) => typeParameter.name) ?? [];
|
|
1476
|
-
const parametersText = renderUnknownParameters(declaration.parameters, typeParameterNames);
|
|
1477
|
-
const returnTypeText = renderPortableType(declaration.returnType, typeParameterNames);
|
|
2323
|
+
const parametersText = renderUnknownParameters(declaration.parameters, typeParameterNames, facade.localTypeNameRemaps);
|
|
2324
|
+
const returnTypeText = renderPortableType(declaration.returnType, typeParameterNames, facade.localTypeNameRemaps);
|
|
1478
2325
|
const sourceSignatures = (facade.sourceSignatures ?? [])
|
|
1479
|
-
.map((signature) => `${signature.typeParametersText}(${signature.
|
|
2326
|
+
.map((signature) => `${signature.typeParametersText}(${signature.parameters
|
|
2327
|
+
.map((parameter) => `${parameter.prefixText}${parameter.typeText}`)
|
|
2328
|
+
.join(", ")}):${signature.returnTypeText}`)
|
|
1480
2329
|
.sort((left, right) => left.localeCompare(right))
|
|
1481
2330
|
.join("||");
|
|
1482
2331
|
return `${typeParametersText}(${parametersText}):${returnTypeText}|source=${sourceSignatures}`;
|
|
1483
2332
|
};
|
|
1484
|
-
const normalizeVariableFacade = (declarator) =>
|
|
2333
|
+
const normalizeVariableFacade = (declarator, localTypeNameRemaps) => {
|
|
2334
|
+
const functionType = resolveFunctionTypeFromValueDeclarator(declarator);
|
|
2335
|
+
if (functionType) {
|
|
2336
|
+
return JSON.stringify(buildSemanticSignatureFromFunctionType(functionType, localTypeNameRemaps));
|
|
2337
|
+
}
|
|
2338
|
+
return renderPortableType(declarator?.type, [], localTypeNameRemaps);
|
|
2339
|
+
};
|
|
1485
2340
|
const sameFacade = (() => {
|
|
1486
2341
|
if (existing.facade.kind !== valueExport.facade.kind)
|
|
1487
2342
|
return false;
|
|
@@ -1492,8 +2347,8 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1492
2347
|
}
|
|
1493
2348
|
if (existing.facade.kind === "variable" &&
|
|
1494
2349
|
valueExport.facade.kind === "variable") {
|
|
1495
|
-
return (normalizeVariableFacade(existing.facade.declarator) ===
|
|
1496
|
-
normalizeVariableFacade(valueExport.facade.declarator));
|
|
2350
|
+
return (normalizeVariableFacade(existing.facade.declarator, existing.facade.localTypeNameRemaps) ===
|
|
2351
|
+
normalizeVariableFacade(valueExport.facade.declarator, valueExport.facade.localTypeNameRemaps));
|
|
1497
2352
|
}
|
|
1498
2353
|
return false;
|
|
1499
2354
|
})();
|
|
@@ -1526,32 +2381,113 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1526
2381
|
}
|
|
1527
2382
|
return { ok: true, value: undefined };
|
|
1528
2383
|
};
|
|
2384
|
+
const registerCrossNamespaceReexport = (opts) => {
|
|
2385
|
+
if (opts.declaringNamespace === namespace)
|
|
2386
|
+
return;
|
|
2387
|
+
const moduleSpecifier = `./${moduleNamespacePath(opts.declaringNamespace)}.js`;
|
|
2388
|
+
const key = `${moduleSpecifier}|${opts.kind}`;
|
|
2389
|
+
const specifier = opts.exportName === opts.localName
|
|
2390
|
+
? opts.exportName
|
|
2391
|
+
: `${opts.localName} as ${opts.exportName}`;
|
|
2392
|
+
const existing = crossNamespaceReexportsGrouped.get(key) ?? [];
|
|
2393
|
+
existing.push(specifier);
|
|
2394
|
+
crossNamespaceReexportsGrouped.set(key, existing);
|
|
2395
|
+
};
|
|
2396
|
+
const registerCrossNamespaceTypeDeclaration = (symbol) => {
|
|
2397
|
+
if (symbol.declaringNamespace === namespace)
|
|
2398
|
+
return;
|
|
2399
|
+
const key = `${symbol.declaringNamespace}|${symbol.declaringClassName}|${symbol.localName}|${symbol.kind}`;
|
|
2400
|
+
if (seenCrossNamespaceTypeDeclarationKeys.has(key))
|
|
2401
|
+
return;
|
|
2402
|
+
seenCrossNamespaceTypeDeclarationKeys.add(key);
|
|
2403
|
+
crossNamespaceTypeDeclarations.push(symbol);
|
|
2404
|
+
};
|
|
2405
|
+
const registerSourceTypeImportCandidates = (sourceIndex, moduleKey, moduleFilePath) => {
|
|
2406
|
+
for (const [localName, imported] of sourceIndex.typeImportsByLocalName) {
|
|
2407
|
+
if (sourceIndex.wrapperImportsByLocalName.has(localName))
|
|
2408
|
+
continue;
|
|
2409
|
+
const internalImport = resolveSourceTypeImportBinding({
|
|
2410
|
+
context: "internal",
|
|
2411
|
+
currentNamespace: namespace,
|
|
2412
|
+
currentModuleKey: moduleKey,
|
|
2413
|
+
localName,
|
|
2414
|
+
imported,
|
|
2415
|
+
modulesByFileKey,
|
|
2416
|
+
});
|
|
2417
|
+
if (!internalImport.ok)
|
|
2418
|
+
return internalImport;
|
|
2419
|
+
if (internalImport.value) {
|
|
2420
|
+
const registered = registerSourceTypeImportBinding(internalTypeImportByAlias, internalImport.value, namespace, moduleFilePath);
|
|
2421
|
+
if (!registered.ok)
|
|
2422
|
+
return registered;
|
|
2423
|
+
}
|
|
2424
|
+
const facadeImport = resolveSourceTypeImportBinding({
|
|
2425
|
+
context: "facade",
|
|
2426
|
+
currentNamespace: namespace,
|
|
2427
|
+
currentModuleKey: moduleKey,
|
|
2428
|
+
localName,
|
|
2429
|
+
imported,
|
|
2430
|
+
modulesByFileKey,
|
|
2431
|
+
});
|
|
2432
|
+
if (!facadeImport.ok)
|
|
2433
|
+
return facadeImport;
|
|
2434
|
+
if (facadeImport.value) {
|
|
2435
|
+
const registered = registerSourceTypeImportBinding(facadeTypeImportByAlias, facadeImport.value, namespace, moduleFilePath);
|
|
2436
|
+
if (!registered.ok)
|
|
2437
|
+
return registered;
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
return { ok: true, value: undefined };
|
|
2441
|
+
};
|
|
2442
|
+
const registerFacadeLocalTypeReferenceImports = (opts) => {
|
|
2443
|
+
const typeParameterNames = new Set((opts.typeParameters ?? []).map((typeParameter) => typeParameter.name));
|
|
2444
|
+
const referencedNames = new Set();
|
|
2445
|
+
for (const parameterType of opts.parameterTypes) {
|
|
2446
|
+
collectReferencedPortableTypeNames(parameterType, typeParameterNames, referencedNames);
|
|
2447
|
+
}
|
|
2448
|
+
collectReferencedPortableTypeNames(opts.returnType, typeParameterNames, referencedNames);
|
|
2449
|
+
const helperTypeRemaps = registerInternalHelperTypeClosure({
|
|
2450
|
+
declarationModule: opts.declarationModule,
|
|
2451
|
+
sourceIndex: opts.sourceIndex,
|
|
2452
|
+
referencedNames,
|
|
2453
|
+
});
|
|
2454
|
+
if (!helperTypeRemaps.ok)
|
|
2455
|
+
return helperTypeRemaps;
|
|
2456
|
+
if (!opts.sourceIndex)
|
|
2457
|
+
return helperTypeRemaps;
|
|
2458
|
+
if (opts.declarationNamespace === namespace) {
|
|
2459
|
+
return helperTypeRemaps;
|
|
2460
|
+
}
|
|
2461
|
+
const moduleSpecifier = `./${moduleNamespacePath(opts.declarationNamespace)}.js`;
|
|
2462
|
+
for (const referencedName of referencedNames) {
|
|
2463
|
+
if (!opts.sourceIndex.exportedTypeDeclarationNames.has(referencedName)) {
|
|
2464
|
+
continue;
|
|
2465
|
+
}
|
|
2466
|
+
const registered = registerSourceTypeImportBinding(facadeTypeImportByAlias, {
|
|
2467
|
+
importedName: referencedName,
|
|
2468
|
+
localName: referencedName,
|
|
2469
|
+
source: moduleSpecifier,
|
|
2470
|
+
}, namespace, opts.declarationFilePath);
|
|
2471
|
+
if (!registered.ok)
|
|
2472
|
+
return registered;
|
|
2473
|
+
}
|
|
2474
|
+
return helperTypeRemaps;
|
|
2475
|
+
};
|
|
1529
2476
|
for (const module of moduleList.sort((left, right) => left.filePath.localeCompare(right.filePath))) {
|
|
1530
2477
|
const moduleKey = normalizeModuleFileKey(module.filePath);
|
|
1531
2478
|
const sourceIndex = sourceIndexByFileKey.get(moduleKey);
|
|
1532
2479
|
if (sourceIndex) {
|
|
2480
|
+
const registered = registerSourceTypeImportCandidates(sourceIndex, moduleKey, module.filePath);
|
|
2481
|
+
if (!registered.ok)
|
|
2482
|
+
return registered;
|
|
1533
2483
|
const exportedAliasDecls = module.body.filter((stmt) => stmt.kind === "typeAliasDeclaration" && stmt.isExported);
|
|
1534
2484
|
for (const alias of exportedAliasDecls) {
|
|
1535
2485
|
const sourceAlias = sourceIndex.typeAliasesByName.get(alias.name);
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
const typeArgs = sourceAlias && sourceAlias.typeParameterNames.length > 0
|
|
1542
|
-
? `<${sourceAlias.typeParameterNames.join(", ")}>`
|
|
1543
|
-
: alias.typeParameters && alias.typeParameters.length > 0
|
|
1544
|
-
? `<${alias.typeParameters.map((tp) => tp.name).join(", ")}>`
|
|
1545
|
-
: "";
|
|
1546
|
-
sourceAliasLines.add(`export type ${alias.name}${sourceTypeParams} = ${internalName}${typeArgs};`);
|
|
1547
|
-
sourceAliasInternalImports.add(internalName);
|
|
1548
|
-
continue;
|
|
1549
|
-
}
|
|
1550
|
-
const rhs = renderPortableType(alias.type, alias.typeParameters?.map((tp) => tp.name) ?? []);
|
|
1551
|
-
const shouldPreferSourceAliasText = sourceAlias !== undefined &&
|
|
1552
|
-
!typeNodeUsesImportedTypeNames(sourceAlias.type, sourceIndex.typeImportsByLocalName) &&
|
|
1553
|
-
/__\d+\b|\$instance\b/.test(rhs);
|
|
1554
|
-
sourceAliasLines.add(`export type ${alias.name}${sourceTypeParams} = ${shouldPreferSourceAliasText ? sourceAlias.typeText : rhs};`);
|
|
2486
|
+
sourceAliasPlans.push({
|
|
2487
|
+
declaration: alias,
|
|
2488
|
+
sourceAlias,
|
|
2489
|
+
typeImportsByLocalName: sourceIndex.typeImportsByLocalName,
|
|
2490
|
+
});
|
|
1555
2491
|
}
|
|
1556
2492
|
const exportedClasses = module.body.filter((stmt) => stmt.kind === "classDeclaration" && stmt.isExported);
|
|
1557
2493
|
const exportedInterfaces = module.body.filter((stmt) => stmt.kind === "interfaceDeclaration" && stmt.isExported);
|
|
@@ -1692,6 +2628,17 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1692
2628
|
const exportKind = classifyDeclarationKind(declaration, declarationModule.filePath, exportItem.name);
|
|
1693
2629
|
if (!exportKind.ok)
|
|
1694
2630
|
return exportKind;
|
|
2631
|
+
if (declarationModule.namespace !== namespace) {
|
|
2632
|
+
registerCrossNamespaceReexport({
|
|
2633
|
+
declaringNamespace: declarationModule.namespace,
|
|
2634
|
+
exportName: exportItem.name,
|
|
2635
|
+
localName: resolved.value.clrName,
|
|
2636
|
+
kind: exportKind.value === "interface" ||
|
|
2637
|
+
exportKind.value === "typeAlias"
|
|
2638
|
+
? "type"
|
|
2639
|
+
: "value",
|
|
2640
|
+
});
|
|
2641
|
+
}
|
|
1695
2642
|
if (exportKind.value === "function") {
|
|
1696
2643
|
const functionDeclaration = declaration.kind === "functionDeclaration"
|
|
1697
2644
|
? declaration
|
|
@@ -1702,6 +2649,24 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1702
2649
|
error: `Invalid function export '${exportItem.name}' in ${declarationModule.filePath}: expected function declaration.`,
|
|
1703
2650
|
};
|
|
1704
2651
|
}
|
|
2652
|
+
const declarationModuleKey = normalizeModuleFileKey(declarationModule.filePath);
|
|
2653
|
+
const declarationSourceIndex = sourceIndexByFileKey.get(declarationModuleKey);
|
|
2654
|
+
if (declarationSourceIndex) {
|
|
2655
|
+
const registered = registerSourceTypeImportCandidates(declarationSourceIndex, declarationModuleKey, declarationModule.filePath);
|
|
2656
|
+
if (!registered.ok)
|
|
2657
|
+
return registered;
|
|
2658
|
+
}
|
|
2659
|
+
const registeredLocalTypeRefs = registerFacadeLocalTypeReferenceImports({
|
|
2660
|
+
declarationModule,
|
|
2661
|
+
declarationNamespace: declarationModule.namespace,
|
|
2662
|
+
declarationFilePath: declarationModule.filePath,
|
|
2663
|
+
sourceIndex: declarationSourceIndex,
|
|
2664
|
+
typeParameters: functionDeclaration.typeParameters,
|
|
2665
|
+
parameterTypes: functionDeclaration.parameters.map((parameter) => parameter.type),
|
|
2666
|
+
returnType: functionDeclaration.returnType,
|
|
2667
|
+
});
|
|
2668
|
+
if (!registeredLocalTypeRefs.ok)
|
|
2669
|
+
return registeredLocalTypeRefs;
|
|
1705
2670
|
const registered = registerValueExport({
|
|
1706
2671
|
exportName: exportItem.name,
|
|
1707
2672
|
binding: {
|
|
@@ -1713,6 +2678,7 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1713
2678
|
facade: {
|
|
1714
2679
|
kind: "function",
|
|
1715
2680
|
declaration: functionDeclaration,
|
|
2681
|
+
localTypeNameRemaps: registeredLocalTypeRefs.value,
|
|
1716
2682
|
sourceSignatures: sourceIndexByFileKey
|
|
1717
2683
|
.get(normalizeModuleFileKey(declarationModule.filePath))
|
|
1718
2684
|
?.exportedFunctionSignaturesByName.get(resolved.value.clrName) ?? [],
|
|
@@ -1732,23 +2698,63 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1732
2698
|
error: `Invalid variable export '${exportItem.name}' in ${declarationModule.filePath}: expected variable declaration.`,
|
|
1733
2699
|
};
|
|
1734
2700
|
}
|
|
2701
|
+
const declarationModuleKey = normalizeModuleFileKey(declarationModule.filePath);
|
|
2702
|
+
const declarationSourceIndex = sourceIndexByFileKey.get(declarationModuleKey);
|
|
2703
|
+
if (declarationSourceIndex) {
|
|
2704
|
+
const registered = registerSourceTypeImportCandidates(declarationSourceIndex, declarationModuleKey, declarationModule.filePath);
|
|
2705
|
+
if (!registered.ok)
|
|
2706
|
+
return registered;
|
|
2707
|
+
}
|
|
1735
2708
|
const declarator = declarationStatement.declarations.find((candidate) => candidate.name.kind === "identifierPattern" &&
|
|
1736
2709
|
candidate.name.name === resolved.value.clrName);
|
|
2710
|
+
const exportedFunctionType = resolveFunctionTypeFromValueDeclarator(declarator && declarator.name.kind === "identifierPattern"
|
|
2711
|
+
? {
|
|
2712
|
+
kind: declarator.kind,
|
|
2713
|
+
name: declarator.name,
|
|
2714
|
+
type: declarator.type,
|
|
2715
|
+
initializer: declarator.initializer,
|
|
2716
|
+
}
|
|
2717
|
+
: undefined);
|
|
2718
|
+
const registeredLocalTypeRefs = registerFacadeLocalTypeReferenceImports({
|
|
2719
|
+
declarationModule,
|
|
2720
|
+
declarationNamespace: declarationModule.namespace,
|
|
2721
|
+
declarationFilePath: declarationModule.filePath,
|
|
2722
|
+
sourceIndex: declarationSourceIndex,
|
|
2723
|
+
typeParameters: undefined,
|
|
2724
|
+
parameterTypes: exportedFunctionType
|
|
2725
|
+
? [exportedFunctionType]
|
|
2726
|
+
: declarator?.type
|
|
2727
|
+
? [declarator.type]
|
|
2728
|
+
: [],
|
|
2729
|
+
returnType: undefined,
|
|
2730
|
+
});
|
|
2731
|
+
if (!registeredLocalTypeRefs.ok)
|
|
2732
|
+
return registeredLocalTypeRefs;
|
|
1737
2733
|
const registered = registerValueExport({
|
|
1738
2734
|
exportName: exportItem.name,
|
|
1739
2735
|
binding: {
|
|
1740
|
-
kind: "field",
|
|
2736
|
+
kind: exportedFunctionType ? "functionType" : "field",
|
|
1741
2737
|
clrName: resolved.value.clrName,
|
|
1742
2738
|
declaringClrType: toClrTypeName(declarationModule.namespace, declarationModule.className),
|
|
1743
2739
|
declaringAssemblyName: assemblyName,
|
|
2740
|
+
semanticType: exportedFunctionType
|
|
2741
|
+
? undefined
|
|
2742
|
+
: rewriteBindingSemanticType(declarator?.type, registeredLocalTypeRefs.value),
|
|
2743
|
+
semanticSignature: exportedFunctionType
|
|
2744
|
+
? buildSemanticSignatureFromFunctionType(exportedFunctionType, registeredLocalTypeRefs.value)
|
|
2745
|
+
: undefined,
|
|
1744
2746
|
},
|
|
1745
2747
|
facade: {
|
|
1746
2748
|
kind: "variable",
|
|
2749
|
+
localTypeNameRemaps: registeredLocalTypeRefs.value,
|
|
2750
|
+
sourceType: declarationSourceIndex?.exportedValueTypesByName.get(resolved.value.clrName),
|
|
2751
|
+
sourceSignatures: declarationSourceIndex?.exportedFunctionSignaturesByName.get(resolved.value.clrName) ?? [],
|
|
1747
2752
|
declarator: declarator && declarator.name.kind === "identifierPattern"
|
|
1748
2753
|
? {
|
|
1749
2754
|
kind: declarator.kind,
|
|
1750
2755
|
name: declarator.name,
|
|
1751
2756
|
type: declarator.type,
|
|
2757
|
+
initializer: declarator.initializer,
|
|
1752
2758
|
}
|
|
1753
2759
|
: undefined,
|
|
1754
2760
|
},
|
|
@@ -1761,6 +2767,25 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1761
2767
|
exportKind.value === "interface" ||
|
|
1762
2768
|
exportKind.value === "enum" ||
|
|
1763
2769
|
exportKind.value === "typeAlias") {
|
|
2770
|
+
if (declarationModule.namespace !== namespace) {
|
|
2771
|
+
registerCrossNamespaceTypeDeclaration({
|
|
2772
|
+
exportName: exportItem.name,
|
|
2773
|
+
localName: resolved.value.clrName,
|
|
2774
|
+
kind: exportKind.value,
|
|
2775
|
+
declaration,
|
|
2776
|
+
declaringNamespace: declarationModule.namespace,
|
|
2777
|
+
declaringClassName: declarationModule.className,
|
|
2778
|
+
declaringFilePath: declarationModule.filePath,
|
|
2779
|
+
});
|
|
2780
|
+
continue;
|
|
2781
|
+
}
|
|
2782
|
+
const declarationModuleKey = normalizeModuleFileKey(declarationModule.filePath);
|
|
2783
|
+
const declarationSourceIndex = sourceIndexByFileKey.get(declarationModuleKey);
|
|
2784
|
+
if (declarationSourceIndex) {
|
|
2785
|
+
const registered = registerSourceTypeImportCandidates(declarationSourceIndex, declarationModuleKey, declarationModule.filePath);
|
|
2786
|
+
if (!registered.ok)
|
|
2787
|
+
return registered;
|
|
2788
|
+
}
|
|
1764
2789
|
if (exportKind.value === "typeAlias" &&
|
|
1765
2790
|
declaration.kind === "typeAliasDeclaration" &&
|
|
1766
2791
|
declaration.type.kind !== "objectType") {
|
|
@@ -1812,6 +2837,18 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1812
2837
|
symbol.kind === "interface" ||
|
|
1813
2838
|
symbol.kind === "enum" ||
|
|
1814
2839
|
symbol.kind === "typeAlias") {
|
|
2840
|
+
if (symbol.declaringNamespace !== namespace) {
|
|
2841
|
+
registerCrossNamespaceReexport({
|
|
2842
|
+
declaringNamespace: symbol.declaringNamespace,
|
|
2843
|
+
exportName: symbol.exportName,
|
|
2844
|
+
localName: symbol.localName,
|
|
2845
|
+
kind: symbol.kind === "interface" || symbol.kind === "typeAlias"
|
|
2846
|
+
? "type"
|
|
2847
|
+
: "value",
|
|
2848
|
+
});
|
|
2849
|
+
registerCrossNamespaceTypeDeclaration(symbol);
|
|
2850
|
+
continue;
|
|
2851
|
+
}
|
|
1815
2852
|
if (symbol.kind === "typeAlias" &&
|
|
1816
2853
|
symbol.declaration.kind === "typeAliasDeclaration" &&
|
|
1817
2854
|
symbol.declaration.type.kind !== "objectType") {
|
|
@@ -1824,11 +2861,45 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1824
2861
|
}
|
|
1825
2862
|
}
|
|
1826
2863
|
if (symbol.kind === "function") {
|
|
2864
|
+
if (symbol.declaringNamespace !== namespace) {
|
|
2865
|
+
registerCrossNamespaceReexport({
|
|
2866
|
+
declaringNamespace: symbol.declaringNamespace,
|
|
2867
|
+
exportName: symbol.exportName,
|
|
2868
|
+
localName: symbol.localName,
|
|
2869
|
+
kind: "value",
|
|
2870
|
+
});
|
|
2871
|
+
}
|
|
1827
2872
|
const functionDeclaration = symbol.declaration.kind === "functionDeclaration"
|
|
1828
2873
|
? symbol.declaration
|
|
1829
2874
|
: undefined;
|
|
1830
2875
|
if (!functionDeclaration)
|
|
1831
2876
|
continue;
|
|
2877
|
+
const symbolModuleKey = normalizeModuleFileKey(symbol.declaringFilePath);
|
|
2878
|
+
const symbolSourceIndex = sourceIndexByFileKey.get(symbolModuleKey);
|
|
2879
|
+
const symbolDeclarationModule = modulesByFileKey.get(symbolModuleKey);
|
|
2880
|
+
if (!symbolDeclarationModule) {
|
|
2881
|
+
return {
|
|
2882
|
+
ok: false,
|
|
2883
|
+
error: `Unable to resolve declaring module for '${symbol.exportName}' while generating ${symbol.declaringFilePath}.\n` +
|
|
2884
|
+
"First-party bindings generation requires a stable source module for each exported value.",
|
|
2885
|
+
};
|
|
2886
|
+
}
|
|
2887
|
+
if (symbolSourceIndex) {
|
|
2888
|
+
const registered = registerSourceTypeImportCandidates(symbolSourceIndex, symbolModuleKey, symbol.declaringFilePath);
|
|
2889
|
+
if (!registered.ok)
|
|
2890
|
+
return registered;
|
|
2891
|
+
}
|
|
2892
|
+
const registeredLocalTypeRefs = registerFacadeLocalTypeReferenceImports({
|
|
2893
|
+
declarationModule: symbolDeclarationModule,
|
|
2894
|
+
declarationNamespace: symbol.declaringNamespace,
|
|
2895
|
+
declarationFilePath: symbol.declaringFilePath,
|
|
2896
|
+
sourceIndex: symbolSourceIndex,
|
|
2897
|
+
typeParameters: functionDeclaration.typeParameters,
|
|
2898
|
+
parameterTypes: functionDeclaration.parameters.map((parameter) => parameter.type),
|
|
2899
|
+
returnType: functionDeclaration.returnType,
|
|
2900
|
+
});
|
|
2901
|
+
if (!registeredLocalTypeRefs.ok)
|
|
2902
|
+
return registeredLocalTypeRefs;
|
|
1832
2903
|
const isLocalContainerMember = symbol.declaringNamespace === module.namespace &&
|
|
1833
2904
|
symbol.declaringClassName === module.className;
|
|
1834
2905
|
if (isLocalContainerMember) {
|
|
@@ -1836,6 +2907,11 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1836
2907
|
exportName: symbol.exportName,
|
|
1837
2908
|
localName: symbol.localName,
|
|
1838
2909
|
declaration: functionDeclaration,
|
|
2910
|
+
localTypeNameRemaps: registeredLocalTypeRefs.value,
|
|
2911
|
+
sourceSignatures: sourceIndexByFileKey
|
|
2912
|
+
.get(normalizeModuleFileKey(symbol.declaringFilePath))
|
|
2913
|
+
?.exportedFunctionSignaturesByName.get(symbol.localName) ??
|
|
2914
|
+
[],
|
|
1839
2915
|
});
|
|
1840
2916
|
}
|
|
1841
2917
|
const registered = registerValueExport({
|
|
@@ -1849,6 +2925,7 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1849
2925
|
facade: {
|
|
1850
2926
|
kind: "function",
|
|
1851
2927
|
declaration: functionDeclaration,
|
|
2928
|
+
localTypeNameRemaps: registeredLocalTypeRefs.value,
|
|
1852
2929
|
sourceSignatures: sourceIndexByFileKey
|
|
1853
2930
|
.get(normalizeModuleFileKey(symbol.declaringFilePath))
|
|
1854
2931
|
?.exportedFunctionSignaturesByName.get(symbol.localName) ??
|
|
@@ -1860,13 +2937,60 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1860
2937
|
continue;
|
|
1861
2938
|
}
|
|
1862
2939
|
if (symbol.kind === "variable") {
|
|
2940
|
+
if (symbol.declaringNamespace !== namespace) {
|
|
2941
|
+
registerCrossNamespaceReexport({
|
|
2942
|
+
declaringNamespace: symbol.declaringNamespace,
|
|
2943
|
+
exportName: symbol.exportName,
|
|
2944
|
+
localName: symbol.localName,
|
|
2945
|
+
kind: "value",
|
|
2946
|
+
});
|
|
2947
|
+
}
|
|
1863
2948
|
const declaration = symbol.declaration.kind === "variableDeclaration"
|
|
1864
2949
|
? symbol.declaration
|
|
1865
2950
|
: undefined;
|
|
1866
2951
|
if (!declaration)
|
|
1867
2952
|
continue;
|
|
2953
|
+
const symbolModuleKey = normalizeModuleFileKey(symbol.declaringFilePath);
|
|
2954
|
+
const symbolSourceIndex = sourceIndexByFileKey.get(symbolModuleKey);
|
|
2955
|
+
const symbolDeclarationModule = modulesByFileKey.get(symbolModuleKey);
|
|
2956
|
+
if (!symbolDeclarationModule) {
|
|
2957
|
+
return {
|
|
2958
|
+
ok: false,
|
|
2959
|
+
error: `Unable to resolve declaring module for '${symbol.exportName}' while generating ${symbol.declaringFilePath}.\n` +
|
|
2960
|
+
"First-party bindings generation requires a stable source module for each exported value.",
|
|
2961
|
+
};
|
|
2962
|
+
}
|
|
2963
|
+
if (symbolSourceIndex) {
|
|
2964
|
+
const registered = registerSourceTypeImportCandidates(symbolSourceIndex, symbolModuleKey, symbol.declaringFilePath);
|
|
2965
|
+
if (!registered.ok)
|
|
2966
|
+
return registered;
|
|
2967
|
+
}
|
|
1868
2968
|
const declarator = declaration.declarations.find((candidate) => candidate.name.kind === "identifierPattern" &&
|
|
1869
2969
|
candidate.name.name === symbol.localName);
|
|
2970
|
+
const exportDeclarator = declarator && declarator.name.kind === "identifierPattern"
|
|
2971
|
+
? {
|
|
2972
|
+
kind: declarator.kind,
|
|
2973
|
+
name: declarator.name,
|
|
2974
|
+
type: declarator.type,
|
|
2975
|
+
initializer: declarator.initializer,
|
|
2976
|
+
}
|
|
2977
|
+
: undefined;
|
|
2978
|
+
const exportedFunctionType = resolveFunctionTypeFromValueDeclarator(exportDeclarator);
|
|
2979
|
+
const registeredLocalTypeRefs = registerFacadeLocalTypeReferenceImports({
|
|
2980
|
+
declarationModule: symbolDeclarationModule,
|
|
2981
|
+
declarationNamespace: symbol.declaringNamespace,
|
|
2982
|
+
declarationFilePath: symbol.declaringFilePath,
|
|
2983
|
+
sourceIndex: symbolSourceIndex,
|
|
2984
|
+
typeParameters: undefined,
|
|
2985
|
+
parameterTypes: exportedFunctionType
|
|
2986
|
+
? [exportedFunctionType]
|
|
2987
|
+
: declarator?.type
|
|
2988
|
+
? [declarator.type]
|
|
2989
|
+
: [],
|
|
2990
|
+
returnType: undefined,
|
|
2991
|
+
});
|
|
2992
|
+
if (!registeredLocalTypeRefs.ok)
|
|
2993
|
+
return registeredLocalTypeRefs;
|
|
1870
2994
|
const isLocalContainerMember = symbol.declaringNamespace === module.namespace &&
|
|
1871
2995
|
symbol.declaringClassName === module.className;
|
|
1872
2996
|
if (isLocalContainerMember) {
|
|
@@ -1874,32 +2998,37 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1874
2998
|
exportName: symbol.exportName,
|
|
1875
2999
|
localName: symbol.localName,
|
|
1876
3000
|
declaration,
|
|
1877
|
-
declarator:
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
3001
|
+
declarator: exportDeclarator,
|
|
3002
|
+
localTypeNameRemaps: registeredLocalTypeRefs.value,
|
|
3003
|
+
sourceType: sourceIndexByFileKey
|
|
3004
|
+
.get(normalizeModuleFileKey(symbol.declaringFilePath))
|
|
3005
|
+
?.exportedValueTypesByName.get(symbol.localName),
|
|
3006
|
+
sourceSignatures: sourceIndexByFileKey
|
|
3007
|
+
.get(normalizeModuleFileKey(symbol.declaringFilePath))
|
|
3008
|
+
?.exportedFunctionSignaturesByName.get(symbol.localName) ??
|
|
3009
|
+
[],
|
|
1884
3010
|
});
|
|
1885
3011
|
}
|
|
1886
3012
|
const registered = registerValueExport({
|
|
1887
3013
|
exportName: symbol.exportName,
|
|
1888
3014
|
binding: {
|
|
1889
|
-
kind: "field",
|
|
3015
|
+
kind: exportedFunctionType ? "functionType" : "field",
|
|
1890
3016
|
clrName: symbol.localName,
|
|
1891
3017
|
declaringClrType: toClrTypeName(symbol.declaringNamespace, symbol.declaringClassName),
|
|
1892
3018
|
declaringAssemblyName: assemblyName,
|
|
3019
|
+
semanticType: exportedFunctionType
|
|
3020
|
+
? undefined
|
|
3021
|
+
: rewriteBindingSemanticType(exportDeclarator?.type, registeredLocalTypeRefs.value),
|
|
3022
|
+
semanticSignature: exportedFunctionType
|
|
3023
|
+
? buildSemanticSignatureFromFunctionType(exportedFunctionType, registeredLocalTypeRefs.value)
|
|
3024
|
+
: undefined,
|
|
1893
3025
|
},
|
|
1894
3026
|
facade: {
|
|
1895
3027
|
kind: "variable",
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
type: declarator.type,
|
|
1901
|
-
}
|
|
1902
|
-
: undefined,
|
|
3028
|
+
localTypeNameRemaps: registeredLocalTypeRefs.value,
|
|
3029
|
+
sourceType: symbolSourceIndex?.exportedValueTypesByName.get(symbol.localName),
|
|
3030
|
+
sourceSignatures: symbolSourceIndex?.exportedFunctionSignaturesByName.get(symbol.localName) ?? [],
|
|
3031
|
+
declarator: exportDeclarator,
|
|
1903
3032
|
},
|
|
1904
3033
|
});
|
|
1905
3034
|
if (!registered.ok)
|
|
@@ -1914,18 +3043,113 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1914
3043
|
});
|
|
1915
3044
|
}
|
|
1916
3045
|
}
|
|
3046
|
+
const anonymousHelperClassNamesByShape = new Map();
|
|
3047
|
+
const registerAnonymousHelperClass = (emittedName, declaration) => {
|
|
3048
|
+
if (!emittedName.startsWith("__Anon_") &&
|
|
3049
|
+
!declaration.name.startsWith("__Anon_")) {
|
|
3050
|
+
return;
|
|
3051
|
+
}
|
|
3052
|
+
const members = [];
|
|
3053
|
+
for (const member of declaration.members) {
|
|
3054
|
+
if (member.kind === "propertyDeclaration") {
|
|
3055
|
+
if (isPortableMarkerMemberName(member.name))
|
|
3056
|
+
continue;
|
|
3057
|
+
members.push({
|
|
3058
|
+
kind: "propertySignature",
|
|
3059
|
+
name: member.name,
|
|
3060
|
+
type: member.type ?? { kind: "unknownType" },
|
|
3061
|
+
isOptional: false,
|
|
3062
|
+
isReadonly: member.isReadonly,
|
|
3063
|
+
});
|
|
3064
|
+
continue;
|
|
3065
|
+
}
|
|
3066
|
+
if (member.kind === "methodDeclaration") {
|
|
3067
|
+
if (isPortableMarkerMemberName(member.name))
|
|
3068
|
+
continue;
|
|
3069
|
+
members.push({
|
|
3070
|
+
kind: "methodSignature",
|
|
3071
|
+
name: member.name,
|
|
3072
|
+
parameters: member.parameters,
|
|
3073
|
+
returnType: member.returnType,
|
|
3074
|
+
typeParameters: member.typeParameters,
|
|
3075
|
+
});
|
|
3076
|
+
}
|
|
3077
|
+
}
|
|
3078
|
+
const shape = renderPortableType({ kind: "objectType", members }, declaration.typeParameters?.map((typeParameter) => typeParameter.name) ?? [], new Map(), new Map());
|
|
3079
|
+
anonymousHelperClassNamesByShape.set(shape, emittedName);
|
|
3080
|
+
};
|
|
3081
|
+
for (const symbol of typeDeclarations) {
|
|
3082
|
+
if (symbol.kind === "class" &&
|
|
3083
|
+
symbol.declaration.kind === "classDeclaration") {
|
|
3084
|
+
registerAnonymousHelperClass(symbol.localName, symbol.declaration);
|
|
3085
|
+
}
|
|
3086
|
+
}
|
|
3087
|
+
for (const helper of internalHelperTypeDeclarationsByKey.values()) {
|
|
3088
|
+
if (helper.kind === "class") {
|
|
3089
|
+
registerAnonymousHelperClass(helper.emittedName, helper.declaration);
|
|
3090
|
+
}
|
|
3091
|
+
}
|
|
3092
|
+
for (const [moduleKey, sourceIndex] of sourceIndexByFileKey) {
|
|
3093
|
+
const sourceModule = modulesByFileKey.get(moduleKey);
|
|
3094
|
+
if (!sourceModule)
|
|
3095
|
+
continue;
|
|
3096
|
+
for (const [shape, anonymousType,] of sourceIndex.anonymousTypeLiteralsByShape) {
|
|
3097
|
+
const className = anonymousHelperClassNamesByShape.get(shape);
|
|
3098
|
+
if (!className)
|
|
3099
|
+
continue;
|
|
3100
|
+
for (const [memberName, sourceMember] of anonymousType.members) {
|
|
3101
|
+
const wrappersResult = collectExtensionWrapperImportsFromSourceType({
|
|
3102
|
+
startModuleKey: moduleKey,
|
|
3103
|
+
typeNode: sourceMember.typeNode,
|
|
3104
|
+
sourceIndexByFileKey,
|
|
3105
|
+
modulesByFileKey,
|
|
3106
|
+
});
|
|
3107
|
+
if (!wrappersResult.ok)
|
|
3108
|
+
return wrappersResult;
|
|
3109
|
+
const wrappers = wrappersResult.value;
|
|
3110
|
+
const canUseSourceTypeText = !typeNodeUsesImportedTypeNames(sourceMember.typeNode, sourceIndex.typeImportsByLocalName);
|
|
3111
|
+
if (!canUseSourceTypeText &&
|
|
3112
|
+
wrappers.length === 0 &&
|
|
3113
|
+
!sourceMember.isOptional) {
|
|
3114
|
+
continue;
|
|
3115
|
+
}
|
|
3116
|
+
const wrapperRegistered = registerWrapperImports(wrappers, sourceModule.filePath);
|
|
3117
|
+
if (!wrapperRegistered.ok)
|
|
3118
|
+
return wrapperRegistered;
|
|
3119
|
+
memberOverrides.push({
|
|
3120
|
+
className,
|
|
3121
|
+
memberName,
|
|
3122
|
+
sourceTypeText: canUseSourceTypeText
|
|
3123
|
+
? sourceMember.typeText
|
|
3124
|
+
: undefined,
|
|
3125
|
+
replaceWithSourceType: canUseSourceTypeText,
|
|
3126
|
+
isOptional: sourceMember.isOptional,
|
|
3127
|
+
emitOptionalPropertySyntax: true,
|
|
3128
|
+
wrappers,
|
|
3129
|
+
});
|
|
3130
|
+
}
|
|
3131
|
+
}
|
|
3132
|
+
}
|
|
1917
3133
|
plans.push({
|
|
1918
3134
|
namespace,
|
|
1919
3135
|
typeDeclarations: typeDeclarations.sort((left, right) => left.exportName.localeCompare(right.exportName)),
|
|
3136
|
+
internalHelperTypeDeclarations: Array.from(internalHelperTypeDeclarationsByKey.values()).sort((left, right) => left.key.localeCompare(right.key)),
|
|
1920
3137
|
moduleContainers: moduleContainers.sort((left, right) => left.module.className.localeCompare(right.module.className)),
|
|
1921
|
-
|
|
1922
|
-
|
|
3138
|
+
crossNamespaceReexports: finalizeCrossNamespaceReexports(crossNamespaceReexportsGrouped),
|
|
3139
|
+
crossNamespaceTypeDeclarations: crossNamespaceTypeDeclarations.sort((left, right) => {
|
|
3140
|
+
const leftKey = `${left.exportName}|${left.declaringNamespace}|${left.localName}|${left.kind}`;
|
|
3141
|
+
const rightKey = `${right.exportName}|${right.declaringNamespace}|${right.localName}|${right.kind}`;
|
|
3142
|
+
return leftKey.localeCompare(rightKey);
|
|
3143
|
+
}),
|
|
3144
|
+
sourceAliases: sourceAliasPlans.sort((left, right) => left.declaration.name.localeCompare(right.declaration.name)),
|
|
1923
3145
|
memberOverrides: memberOverrides.sort((left, right) => {
|
|
1924
3146
|
const classCmp = left.className.localeCompare(right.className);
|
|
1925
3147
|
if (classCmp !== 0)
|
|
1926
3148
|
return classCmp;
|
|
1927
3149
|
return left.memberName.localeCompare(right.memberName);
|
|
1928
3150
|
}),
|
|
3151
|
+
internalTypeImports: Array.from(internalTypeImportByAlias.values()).sort((left, right) => left.localName.localeCompare(right.localName)),
|
|
3152
|
+
facadeTypeImports: Array.from(facadeTypeImportByAlias.values()).sort((left, right) => left.localName.localeCompare(right.localName)),
|
|
1929
3153
|
wrapperImports: Array.from(wrapperImportByAlias.values()).sort((left, right) => left.aliasName.localeCompare(right.aliasName)),
|
|
1930
3154
|
valueExports: Array.from(valueExportsMap.values()).sort((left, right) => left.exportName.localeCompare(right.exportName)),
|
|
1931
3155
|
});
|
|
@@ -1935,55 +3159,7 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1935
3159
|
value: plans.sort((left, right) => left.namespace.localeCompare(right.namespace)),
|
|
1936
3160
|
};
|
|
1937
3161
|
};
|
|
1938
|
-
const
|
|
1939
|
-
const grouped = new Map();
|
|
1940
|
-
for (const exported of entryModule.exports) {
|
|
1941
|
-
if (exported.kind !== "reexport")
|
|
1942
|
-
continue;
|
|
1943
|
-
const targetModule = resolveLocalModuleFile(exported.fromModule, entryModule.filePath, modulesByFileKey);
|
|
1944
|
-
if (!targetModule) {
|
|
1945
|
-
return {
|
|
1946
|
-
ok: false,
|
|
1947
|
-
error: `Failed to resolve re-export '${exported.name}' from '${exported.fromModule}' in ${entryModule.filePath}.`,
|
|
1948
|
-
};
|
|
1949
|
-
}
|
|
1950
|
-
if (targetModule.namespace === entryModule.namespace)
|
|
1951
|
-
continue;
|
|
1952
|
-
const kind = classifyExportKind(targetModule, exported.originalName);
|
|
1953
|
-
if (kind === "unknown") {
|
|
1954
|
-
return {
|
|
1955
|
-
ok: false,
|
|
1956
|
-
error: `Failed to classify re-export '${exported.name}' from '${exported.fromModule}' in ${entryModule.filePath}.`,
|
|
1957
|
-
};
|
|
1958
|
-
}
|
|
1959
|
-
const moduleSpecifier = `./${moduleNamespacePath(targetModule.namespace)}.js`;
|
|
1960
|
-
const key = `${moduleSpecifier}|${kind}`;
|
|
1961
|
-
const specifier = exported.name === exported.originalName
|
|
1962
|
-
? exported.name
|
|
1963
|
-
: `${exported.originalName} as ${exported.name}`;
|
|
1964
|
-
const list = grouped.get(key) ?? [];
|
|
1965
|
-
list.push(specifier);
|
|
1966
|
-
grouped.set(key, list);
|
|
1967
|
-
}
|
|
1968
|
-
const dtsStatements = [];
|
|
1969
|
-
const jsValueStatements = [];
|
|
1970
|
-
for (const [key, specs] of Array.from(grouped.entries()).sort((a, b) => a[0].localeCompare(b[0]))) {
|
|
1971
|
-
const [moduleSpecifier, kind] = key.split("|");
|
|
1972
|
-
const unique = Array.from(new Set(specs)).sort((a, b) => a.localeCompare(b));
|
|
1973
|
-
if (kind === "type") {
|
|
1974
|
-
dtsStatements.push(`export type { ${unique.join(", ")} } from '${moduleSpecifier}';`);
|
|
1975
|
-
continue;
|
|
1976
|
-
}
|
|
1977
|
-
const statement = `export { ${unique.join(", ")} } from '${moduleSpecifier}';`;
|
|
1978
|
-
dtsStatements.push(statement);
|
|
1979
|
-
jsValueStatements.push(statement);
|
|
1980
|
-
}
|
|
1981
|
-
return {
|
|
1982
|
-
ok: true,
|
|
1983
|
-
value: { dtsStatements, jsValueStatements },
|
|
1984
|
-
};
|
|
1985
|
-
};
|
|
1986
|
-
const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
|
|
3162
|
+
const writeNamespaceArtifacts = (config, outDir, plan) => {
|
|
1987
3163
|
const namespacePath = moduleNamespacePath(plan.namespace);
|
|
1988
3164
|
const namespaceDir = join(outDir, namespacePath);
|
|
1989
3165
|
const internalDir = join(namespaceDir, "internal");
|
|
@@ -1992,7 +3168,8 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
|
|
|
1992
3168
|
const facadeDtsPath = join(outDir, `${namespacePath}.d.ts`);
|
|
1993
3169
|
const facadeJsPath = join(outDir, `${namespacePath}.js`);
|
|
1994
3170
|
const bindingsPath = join(namespaceDir, "bindings.json");
|
|
1995
|
-
const
|
|
3171
|
+
const anonymousStructuralAliases = buildAnonymousStructuralAliasMap(plan);
|
|
3172
|
+
const internalBodyLines = [];
|
|
1996
3173
|
const memberOverridesByClass = new Map();
|
|
1997
3174
|
for (const override of plan.memberOverrides) {
|
|
1998
3175
|
const byMember = memberOverridesByClass.get(override.className) ??
|
|
@@ -2000,47 +3177,29 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
|
|
|
2000
3177
|
byMember.set(override.memberName, override);
|
|
2001
3178
|
memberOverridesByClass.set(override.className, byMember);
|
|
2002
3179
|
}
|
|
2003
|
-
internalLines.push("// Generated by Tsonic - Source bindings");
|
|
2004
|
-
internalLines.push(`// Namespace: ${plan.namespace}`);
|
|
2005
|
-
internalLines.push(`// Assembly: ${config.outputName}`);
|
|
2006
|
-
internalLines.push("");
|
|
2007
|
-
internalLines.push(primitiveImportLine);
|
|
2008
|
-
if (plan.wrapperImports.length > 0) {
|
|
2009
|
-
internalLines.push("");
|
|
2010
|
-
internalLines.push("// Tsonic source member type imports (generated)");
|
|
2011
|
-
for (const wrapperImport of plan.wrapperImports) {
|
|
2012
|
-
if (wrapperImport.importedName === wrapperImport.aliasName) {
|
|
2013
|
-
internalLines.push(`import type { ${wrapperImport.importedName} } from '${wrapperImport.source}';`);
|
|
2014
|
-
continue;
|
|
2015
|
-
}
|
|
2016
|
-
internalLines.push(`import type { ${wrapperImport.importedName} as ${wrapperImport.aliasName} } from '${wrapperImport.source}';`);
|
|
2017
|
-
}
|
|
2018
|
-
internalLines.push("// End Tsonic source member type imports");
|
|
2019
|
-
}
|
|
2020
|
-
internalLines.push("");
|
|
2021
3180
|
const typeBindings = [];
|
|
2022
3181
|
for (const symbol of plan.typeDeclarations) {
|
|
2023
3182
|
if (symbol.kind === "class" &&
|
|
2024
3183
|
symbol.declaration.kind === "classDeclaration") {
|
|
2025
|
-
|
|
3184
|
+
internalBodyLines.push(...renderClassInternal(symbol.declaration, plan.namespace, memberOverridesByClass.get(symbol.declaration.name) ?? new Map()));
|
|
2026
3185
|
typeBindings.push(buildTypeBindingFromClass(symbol.declaration, plan.namespace, config.outputName));
|
|
2027
3186
|
continue;
|
|
2028
3187
|
}
|
|
2029
3188
|
if (symbol.kind === "interface" &&
|
|
2030
3189
|
symbol.declaration.kind === "interfaceDeclaration") {
|
|
2031
|
-
|
|
3190
|
+
internalBodyLines.push(...renderInterfaceInternal(symbol.declaration, plan.namespace, memberOverridesByClass.get(symbol.declaration.name) ?? new Map()));
|
|
2032
3191
|
typeBindings.push(buildTypeBindingFromInterface(symbol.declaration, plan.namespace, config.outputName));
|
|
2033
3192
|
continue;
|
|
2034
3193
|
}
|
|
2035
3194
|
if (symbol.kind === "enum" &&
|
|
2036
3195
|
symbol.declaration.kind === "enumDeclaration") {
|
|
2037
|
-
|
|
3196
|
+
internalBodyLines.push(...renderEnumInternal(symbol.declaration));
|
|
2038
3197
|
typeBindings.push(buildTypeBindingFromEnum(symbol.declaration, plan.namespace, config.outputName));
|
|
2039
3198
|
continue;
|
|
2040
3199
|
}
|
|
2041
3200
|
if (symbol.kind === "typeAlias" &&
|
|
2042
3201
|
symbol.declaration.kind === "typeAliasDeclaration") {
|
|
2043
|
-
|
|
3202
|
+
internalBodyLines.push(...renderStructuralAliasInternal(symbol.declaration, plan.namespace, memberOverridesByClass.get(`${symbol.declaration.name}__Alias${(symbol.declaration.typeParameters?.length ?? 0) > 0
|
|
2044
3203
|
? `_${symbol.declaration.typeParameters?.length ?? 0}`
|
|
2045
3204
|
: ""}`) ?? new Map()));
|
|
2046
3205
|
const binding = buildTypeBindingFromStructuralAlias(symbol.declaration, plan.namespace, config.outputName);
|
|
@@ -2048,10 +3207,137 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
|
|
|
2048
3207
|
typeBindings.push(binding);
|
|
2049
3208
|
}
|
|
2050
3209
|
}
|
|
3210
|
+
const helperRemapsByModuleKey = new Map();
|
|
3211
|
+
for (const helper of plan.internalHelperTypeDeclarations) {
|
|
3212
|
+
const current = new Map(helperRemapsByModuleKey.get(helper.moduleFileKey) ?? []);
|
|
3213
|
+
current.set(helper.originalName, helper.emittedName);
|
|
3214
|
+
helperRemapsByModuleKey.set(helper.moduleFileKey, current);
|
|
3215
|
+
}
|
|
3216
|
+
for (const helper of plan.internalHelperTypeDeclarations) {
|
|
3217
|
+
const localTypeNameRemaps = helperRemapsByModuleKey.get(helper.moduleFileKey) ?? new Map();
|
|
3218
|
+
switch (helper.kind) {
|
|
3219
|
+
case "class":
|
|
3220
|
+
internalBodyLines.push(...renderClassInternal(helper.declaration, helper.declaringNamespace, memberOverridesByClass.get(helper.emittedName) ??
|
|
3221
|
+
memberOverridesByClass.get(helper.declaration.name) ??
|
|
3222
|
+
new Map(), helper.emittedName, localTypeNameRemaps, helper.declaration.name, helper.declaration.name));
|
|
3223
|
+
typeBindings.push(buildTypeBindingFromClass(helper.declaration, helper.declaringNamespace, config.outputName, localTypeNameRemaps));
|
|
3224
|
+
continue;
|
|
3225
|
+
case "interface":
|
|
3226
|
+
internalBodyLines.push(...renderInterfaceInternal(helper.declaration, helper.declaringNamespace, memberOverridesByClass.get(helper.emittedName) ??
|
|
3227
|
+
memberOverridesByClass.get(helper.declaration.name) ??
|
|
3228
|
+
new Map(), helper.emittedName, localTypeNameRemaps, helper.declaration.name, helper.declaration.name));
|
|
3229
|
+
typeBindings.push(buildTypeBindingFromInterface(helper.declaration, helper.declaringNamespace, config.outputName, localTypeNameRemaps));
|
|
3230
|
+
continue;
|
|
3231
|
+
case "enum":
|
|
3232
|
+
internalBodyLines.push(...renderEnumInternal(helper.declaration, helper.emittedName));
|
|
3233
|
+
typeBindings.push(buildTypeBindingFromEnum(helper.declaration, helper.declaringNamespace, config.outputName));
|
|
3234
|
+
continue;
|
|
3235
|
+
case "typeAlias": {
|
|
3236
|
+
const structuralLines = renderStructuralAliasInternal(helper.declaration, helper.declaringNamespace, memberOverridesByClass.get(helper.emittedName) ??
|
|
3237
|
+
memberOverridesByClass.get(`${helper.declaration.name}__Alias${(helper.declaration.typeParameters
|
|
3238
|
+
?.length ?? 0) > 0
|
|
3239
|
+
? `_${helper.declaration
|
|
3240
|
+
.typeParameters?.length ?? 0}`
|
|
3241
|
+
: ""}`) ??
|
|
3242
|
+
new Map(), helper.emittedName, localTypeNameRemaps, `${helper.declaration.name}__Alias${(helper.declaration.typeParameters
|
|
3243
|
+
?.length ?? 0) > 0
|
|
3244
|
+
? `_${helper.declaration.typeParameters
|
|
3245
|
+
?.length ?? 0}`
|
|
3246
|
+
: ""}`, `${helper.declaration.name}__Alias${(helper.declaration.typeParameters
|
|
3247
|
+
?.length ?? 0) > 0
|
|
3248
|
+
? `_${helper.declaration.typeParameters
|
|
3249
|
+
?.length ?? 0}`
|
|
3250
|
+
: ""}`);
|
|
3251
|
+
if (structuralLines.length > 0) {
|
|
3252
|
+
internalBodyLines.push(...structuralLines);
|
|
3253
|
+
const binding = buildTypeBindingFromStructuralAlias(helper.declaration, helper.declaringNamespace, config.outputName, localTypeNameRemaps);
|
|
3254
|
+
if (binding)
|
|
3255
|
+
typeBindings.push(binding);
|
|
3256
|
+
continue;
|
|
3257
|
+
}
|
|
3258
|
+
internalBodyLines.push(...renderTypeAliasInternal(helper.declaration, helper.emittedName, localTypeNameRemaps, anonymousStructuralAliases));
|
|
3259
|
+
continue;
|
|
3260
|
+
}
|
|
3261
|
+
}
|
|
3262
|
+
}
|
|
3263
|
+
const renderedSourceAliases = plan.sourceAliases.map((sourceAliasPlan) => renderSourceAliasPlan(sourceAliasPlan, anonymousStructuralAliases));
|
|
3264
|
+
const sourceAliasLines = renderedSourceAliases.map((entry) => entry.line);
|
|
3265
|
+
const sourceAliasInternalImports = renderedSourceAliases
|
|
3266
|
+
.map((entry) => entry.internalImport)
|
|
3267
|
+
.filter((entry) => entry !== undefined)
|
|
3268
|
+
.sort((left, right) => left.localeCompare(right));
|
|
2051
3269
|
for (const container of plan.moduleContainers) {
|
|
2052
|
-
|
|
3270
|
+
internalBodyLines.push(...renderContainerInternal(container, anonymousStructuralAliases));
|
|
2053
3271
|
typeBindings.push(buildTypeBindingFromContainer(container, plan.namespace, config.outputName));
|
|
2054
3272
|
}
|
|
3273
|
+
for (const symbol of plan.crossNamespaceTypeDeclarations) {
|
|
3274
|
+
if (symbol.kind === "class" &&
|
|
3275
|
+
symbol.declaration.kind === "classDeclaration") {
|
|
3276
|
+
typeBindings.push(buildTypeBindingFromClass(symbol.declaration, symbol.declaringNamespace, config.outputName));
|
|
3277
|
+
continue;
|
|
3278
|
+
}
|
|
3279
|
+
if (symbol.kind === "interface" &&
|
|
3280
|
+
symbol.declaration.kind === "interfaceDeclaration") {
|
|
3281
|
+
typeBindings.push(buildTypeBindingFromInterface(symbol.declaration, symbol.declaringNamespace, config.outputName));
|
|
3282
|
+
continue;
|
|
3283
|
+
}
|
|
3284
|
+
if (symbol.kind === "enum" &&
|
|
3285
|
+
symbol.declaration.kind === "enumDeclaration") {
|
|
3286
|
+
typeBindings.push(buildTypeBindingFromEnum(symbol.declaration, symbol.declaringNamespace, config.outputName));
|
|
3287
|
+
continue;
|
|
3288
|
+
}
|
|
3289
|
+
if (symbol.kind === "typeAlias" &&
|
|
3290
|
+
symbol.declaration.kind === "typeAliasDeclaration") {
|
|
3291
|
+
const binding = buildTypeBindingFromStructuralAlias(symbol.declaration, symbol.declaringNamespace, config.outputName);
|
|
3292
|
+
if (binding)
|
|
3293
|
+
typeBindings.push(binding);
|
|
3294
|
+
}
|
|
3295
|
+
}
|
|
3296
|
+
const internalSourceAliasLines = sourceAliasLines.length > 0
|
|
3297
|
+
? [
|
|
3298
|
+
"",
|
|
3299
|
+
"// Tsonic source type aliases (generated)",
|
|
3300
|
+
...sourceAliasLines,
|
|
3301
|
+
"// End Tsonic source type aliases",
|
|
3302
|
+
]
|
|
3303
|
+
: [];
|
|
3304
|
+
const requiredInternalTypeImports = selectSourceTypeImportsForRenderedText([...internalSourceAliasLines, ...internalBodyLines].join("\n"), plan.internalTypeImports);
|
|
3305
|
+
const internalLines = [];
|
|
3306
|
+
internalLines.push("// Generated by Tsonic - Source bindings");
|
|
3307
|
+
internalLines.push(`// Namespace: ${plan.namespace}`);
|
|
3308
|
+
internalLines.push(`// Assembly: ${config.outputName}`);
|
|
3309
|
+
internalLines.push("");
|
|
3310
|
+
internalLines.push(primitiveImportLine);
|
|
3311
|
+
if (requiredInternalTypeImports.length > 0) {
|
|
3312
|
+
internalLines.push("");
|
|
3313
|
+
internalLines.push("// Tsonic source type imports (generated)");
|
|
3314
|
+
for (const typeImport of requiredInternalTypeImports) {
|
|
3315
|
+
if (typeImport.importedName === typeImport.localName) {
|
|
3316
|
+
internalLines.push(`import type { ${typeImport.importedName} } from '${typeImport.source}';`);
|
|
3317
|
+
continue;
|
|
3318
|
+
}
|
|
3319
|
+
internalLines.push(`import type { ${typeImport.importedName} as ${typeImport.localName} } from '${typeImport.source}';`);
|
|
3320
|
+
}
|
|
3321
|
+
internalLines.push("// End Tsonic source type imports");
|
|
3322
|
+
}
|
|
3323
|
+
if (plan.wrapperImports.length > 0) {
|
|
3324
|
+
internalLines.push("");
|
|
3325
|
+
internalLines.push("// Tsonic source member type imports (generated)");
|
|
3326
|
+
for (const wrapperImport of plan.wrapperImports) {
|
|
3327
|
+
if (wrapperImport.importedName === wrapperImport.aliasName) {
|
|
3328
|
+
internalLines.push(`import type { ${wrapperImport.importedName} } from '${wrapperImport.source}';`);
|
|
3329
|
+
continue;
|
|
3330
|
+
}
|
|
3331
|
+
internalLines.push(`import type { ${wrapperImport.importedName} as ${wrapperImport.aliasName} } from '${wrapperImport.source}';`);
|
|
3332
|
+
}
|
|
3333
|
+
internalLines.push("// End Tsonic source member type imports");
|
|
3334
|
+
}
|
|
3335
|
+
internalLines.push("");
|
|
3336
|
+
if (internalSourceAliasLines.length > 0) {
|
|
3337
|
+
internalLines.push(...internalSourceAliasLines);
|
|
3338
|
+
internalLines.push("");
|
|
3339
|
+
}
|
|
3340
|
+
internalLines.push(...internalBodyLines);
|
|
2055
3341
|
writeFileSync(internalIndexPath, internalLines.join("\n").trimEnd() + "\n", "utf-8");
|
|
2056
3342
|
const internalSpecifier = moduleNamespaceToInternalSpecifier(plan.namespace);
|
|
2057
3343
|
const facadeLines = [];
|
|
@@ -2100,9 +3386,12 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
|
|
|
2100
3386
|
localTypeImports.add(`${symbol.localName}$instance`);
|
|
2101
3387
|
}
|
|
2102
3388
|
}
|
|
2103
|
-
for (const internalImport of
|
|
3389
|
+
for (const internalImport of sourceAliasInternalImports) {
|
|
2104
3390
|
localTypeImports.add(internalImport);
|
|
2105
3391
|
}
|
|
3392
|
+
for (const helper of plan.internalHelperTypeDeclarations) {
|
|
3393
|
+
localTypeImports.add(helper.emittedName);
|
|
3394
|
+
}
|
|
2106
3395
|
if (localTypeImports.size > 0) {
|
|
2107
3396
|
facadeLines.push("");
|
|
2108
3397
|
facadeLines.push("// Tsonic source alias imports (generated)");
|
|
@@ -2111,35 +3400,53 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
|
|
|
2111
3400
|
.join(", ")} } from '${internalSpecifier}';`);
|
|
2112
3401
|
facadeLines.push("// End Tsonic source alias imports");
|
|
2113
3402
|
}
|
|
2114
|
-
if (
|
|
3403
|
+
if (sourceAliasLines.length > 0) {
|
|
2115
3404
|
facadeLines.push("");
|
|
2116
3405
|
facadeLines.push("// Tsonic source type aliases (generated)");
|
|
2117
|
-
facadeLines.push(...
|
|
3406
|
+
facadeLines.push(...sourceAliasLines);
|
|
2118
3407
|
facadeLines.push("// End Tsonic source type aliases");
|
|
2119
3408
|
}
|
|
2120
|
-
if (
|
|
3409
|
+
if (plan.crossNamespaceReexports.dtsStatements.length > 0) {
|
|
2121
3410
|
facadeLines.push("");
|
|
2122
|
-
facadeLines.push("// Tsonic
|
|
2123
|
-
facadeLines.push(...
|
|
2124
|
-
facadeLines.push("// End Tsonic
|
|
3411
|
+
facadeLines.push("// Tsonic cross-namespace re-exports (generated)");
|
|
3412
|
+
facadeLines.push(...plan.crossNamespaceReexports.dtsStatements);
|
|
3413
|
+
facadeLines.push("// End Tsonic cross-namespace re-exports");
|
|
2125
3414
|
}
|
|
2126
3415
|
for (const valueExport of plan.valueExports) {
|
|
2127
3416
|
valueBindings.set(valueExport.exportName, valueExport.binding);
|
|
2128
3417
|
if (valueExport.facade.kind === "function") {
|
|
2129
|
-
const
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
3418
|
+
const sourceSignature = renderSourceFunctionSignature({
|
|
3419
|
+
declaration: valueExport.facade.declaration,
|
|
3420
|
+
sourceSignatures: valueExport.facade.sourceSignatures ?? [],
|
|
3421
|
+
localTypeNameRemaps: valueExport.facade.localTypeNameRemaps,
|
|
3422
|
+
anonymousStructuralAliases,
|
|
3423
|
+
});
|
|
3424
|
+
facadeLines.push(sourceSignature
|
|
3425
|
+
? `export declare function ${valueExport.exportName}${sourceSignature.typeParametersText}(${sourceSignature.parametersText}): ${sourceSignature.returnTypeText};`
|
|
3426
|
+
: `export declare function ${valueExport.exportName}${printTypeParameters(valueExport.facade.declaration.typeParameters)}(${renderUnknownParameters(valueExport.facade.declaration.parameters, valueExport.facade.declaration.typeParameters?.map((typeParameter) => typeParameter.name) ?? [], valueExport.facade.localTypeNameRemaps, anonymousStructuralAliases)}): ${renderPortableType(valueExport.facade.declaration.returnType, valueExport.facade.declaration.typeParameters?.map((typeParameter) => typeParameter.name) ?? [], valueExport.facade.localTypeNameRemaps, anonymousStructuralAliases)};`);
|
|
2134
3427
|
continue;
|
|
2135
3428
|
}
|
|
2136
|
-
|
|
3429
|
+
const sourceFunctionTypeText = renderSourceFunctionType({
|
|
3430
|
+
sourceSignatures: valueExport.facade.sourceSignatures ?? [],
|
|
3431
|
+
localTypeNameRemaps: valueExport.facade.localTypeNameRemaps,
|
|
3432
|
+
anonymousStructuralAliases,
|
|
3433
|
+
});
|
|
3434
|
+
const sourceTypeText = sourceFunctionTypeText ??
|
|
3435
|
+
renderSourceValueType(valueExport.facade.sourceType, valueExport.facade.localTypeNameRemaps, anonymousStructuralAliases);
|
|
3436
|
+
facadeLines.push(`export declare const ${valueExport.exportName}: ${sourceTypeText ??
|
|
3437
|
+
renderPortableType(valueExport.facade.declarator?.type, [], valueExport.facade.localTypeNameRemaps, anonymousStructuralAliases)};`);
|
|
3438
|
+
}
|
|
3439
|
+
const requiredFacadeTypeImports = selectSourceTypeImportsForRenderedText(facadeLines.join("\n"), plan.facadeTypeImports);
|
|
3440
|
+
if (requiredFacadeTypeImports.length > 0) {
|
|
3441
|
+
facadeLines.splice(4, 0, "", "// Tsonic source type imports (generated)", ...requiredFacadeTypeImports.map((typeImport) => typeImport.importedName === typeImport.localName
|
|
3442
|
+
? `import type { ${typeImport.importedName} } from '${typeImport.source}';`
|
|
3443
|
+
: `import type { ${typeImport.importedName} as ${typeImport.localName} } from '${typeImport.source}';`), "// End Tsonic source type imports");
|
|
2137
3444
|
}
|
|
2138
3445
|
if (plan.typeDeclarations.length === 0 &&
|
|
2139
3446
|
plan.moduleContainers.length === 0 &&
|
|
2140
3447
|
plan.valueExports.length === 0 &&
|
|
2141
|
-
|
|
2142
|
-
|
|
3448
|
+
sourceAliasLines.length === 0 &&
|
|
3449
|
+
plan.crossNamespaceReexports.dtsStatements.length === 0) {
|
|
2143
3450
|
facadeLines.push("export {};");
|
|
2144
3451
|
}
|
|
2145
3452
|
writeFileSync(facadeDtsPath, facadeLines.join("\n").trimEnd() + "\n", "utf-8");
|
|
@@ -2148,12 +3455,11 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
|
|
|
2148
3455
|
"// Generated by Tsonic - Source bindings",
|
|
2149
3456
|
"// Module Stub - Do Not Execute",
|
|
2150
3457
|
"",
|
|
2151
|
-
...(
|
|
2152
|
-
entrypointReexports.jsValueStatements.length > 0
|
|
3458
|
+
...(plan.crossNamespaceReexports.jsValueStatements.length > 0
|
|
2153
3459
|
? [
|
|
2154
|
-
"// Tsonic
|
|
2155
|
-
...
|
|
2156
|
-
"// End Tsonic
|
|
3460
|
+
"// Tsonic cross-namespace value re-exports (generated)",
|
|
3461
|
+
...plan.crossNamespaceReexports.jsValueStatements,
|
|
3462
|
+
"// End Tsonic cross-namespace value re-exports",
|
|
2157
3463
|
"",
|
|
2158
3464
|
]
|
|
2159
3465
|
: []),
|
|
@@ -2216,10 +3522,6 @@ export const generateFirstPartyLibraryBindings = (config, bindingsOutDir) => {
|
|
|
2216
3522
|
}
|
|
2217
3523
|
rmSync(bindingsOutDir, { recursive: true, force: true });
|
|
2218
3524
|
mkdirSync(bindingsOutDir, { recursive: true });
|
|
2219
|
-
const modulesByFileKey = new Map();
|
|
2220
|
-
for (const module of graphResult.value.modules) {
|
|
2221
|
-
modulesByFileKey.set(normalizeModuleFileKey(module.filePath), module);
|
|
2222
|
-
}
|
|
2223
3525
|
const sourceIndexByFileKey = new Map();
|
|
2224
3526
|
for (const module of graphResult.value.modules) {
|
|
2225
3527
|
if (module.filePath.startsWith("__tsonic/"))
|
|
@@ -2234,13 +3536,8 @@ export const generateFirstPartyLibraryBindings = (config, bindingsOutDir) => {
|
|
|
2234
3536
|
const plansResult = collectNamespacePlans(graphResult.value.modules, config.outputName, config.rootNamespace, sourceIndexByFileKey);
|
|
2235
3537
|
if (!plansResult.ok)
|
|
2236
3538
|
return plansResult;
|
|
2237
|
-
const entrypointReexportsResult = collectEntrypointReexports(graphResult.value.entryModule, modulesByFileKey);
|
|
2238
|
-
if (!entrypointReexportsResult.ok)
|
|
2239
|
-
return entrypointReexportsResult;
|
|
2240
3539
|
for (const plan of plansResult.value) {
|
|
2241
|
-
const result = writeNamespaceArtifacts(config, bindingsOutDir, plan
|
|
2242
|
-
? entrypointReexportsResult.value
|
|
2243
|
-
: undefined);
|
|
3540
|
+
const result = writeNamespaceArtifacts(config, bindingsOutDir, plan);
|
|
2244
3541
|
if (!result.ok)
|
|
2245
3542
|
return result;
|
|
2246
3543
|
}
|