@tsonic/cli 0.0.71 → 0.0.73
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/aikya/bindings.d.ts +1 -0
- package/dist/aikya/bindings.d.ts.map +1 -1
- package/dist/aikya/bindings.js +23 -0
- package/dist/aikya/bindings.js.map +1 -1
- package/dist/commands/add-npm.d.ts +1 -0
- package/dist/commands/add-npm.d.ts.map +1 -1
- package/dist/commands/add-npm.js +8 -1
- package/dist/commands/add-npm.js.map +1 -1
- package/dist/commands/add-npm.test.js +32 -0
- package/dist/commands/add-npm.test.js.map +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 +2420 -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 +1609 -306
- 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/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,149 @@ 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
|
+
};
|
|
245
|
+
const typeNeedsAnonymousCanonicalization = (candidate) => {
|
|
246
|
+
if (!candidate)
|
|
247
|
+
return false;
|
|
248
|
+
switch (candidate.kind) {
|
|
249
|
+
case "objectType":
|
|
250
|
+
return anonymousStructuralAliases.has(renderPortableShapeType(candidate, typeParametersInScope));
|
|
251
|
+
case "arrayType":
|
|
252
|
+
return typeNeedsAnonymousCanonicalization(candidate.elementType);
|
|
253
|
+
case "tupleType":
|
|
254
|
+
return candidate.elementTypes.some(typeNeedsAnonymousCanonicalization);
|
|
255
|
+
case "unionType":
|
|
256
|
+
case "intersectionType":
|
|
257
|
+
return candidate.types.some(typeNeedsAnonymousCanonicalization);
|
|
258
|
+
case "dictionaryType":
|
|
259
|
+
return (typeNeedsAnonymousCanonicalization(candidate.keyType) ||
|
|
260
|
+
typeNeedsAnonymousCanonicalization(candidate.valueType));
|
|
261
|
+
case "functionType":
|
|
262
|
+
return (candidate.parameters.some((parameter) => typeNeedsAnonymousCanonicalization(parameter.type)) || typeNeedsAnonymousCanonicalization(candidate.returnType));
|
|
263
|
+
case "referenceType":
|
|
264
|
+
return (candidate.typeArguments?.some(typeNeedsAnonymousCanonicalization) ??
|
|
265
|
+
false);
|
|
266
|
+
default:
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
};
|
|
93
270
|
if (!type)
|
|
94
271
|
return "object";
|
|
95
272
|
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;
|
|
273
|
+
case "objectType": {
|
|
274
|
+
const shape = renderPortableShapeType(type, typeParametersInScope);
|
|
275
|
+
const alias = anonymousStructuralAliases.get(shape);
|
|
276
|
+
if (alias) {
|
|
277
|
+
const typeArgs = alias.typeParameters.length > 0
|
|
278
|
+
? `<${alias.typeParameters.join(", ")}>`
|
|
279
|
+
: "";
|
|
280
|
+
return `${alias.name}${typeArgs}`;
|
|
281
|
+
}
|
|
282
|
+
return shape;
|
|
283
|
+
}
|
|
111
284
|
case "arrayType":
|
|
112
|
-
return `${renderPortableType(type.elementType, typeParametersInScope)}[]`;
|
|
285
|
+
return `${renderPortableType(type.elementType, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases)}[]`;
|
|
113
286
|
case "tupleType":
|
|
114
287
|
return `[${type.elementTypes
|
|
115
|
-
.map((item) => renderPortableType(item, typeParametersInScope))
|
|
288
|
+
.map((item) => renderPortableType(item, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases))
|
|
116
289
|
.join(", ")}]`;
|
|
117
290
|
case "unionType":
|
|
118
291
|
return type.types
|
|
119
|
-
.map((item) => renderPortableType(item, typeParametersInScope))
|
|
292
|
+
.map((item) => renderPortableType(item, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases))
|
|
120
293
|
.join(" | ");
|
|
121
294
|
case "intersectionType":
|
|
122
295
|
return type.types
|
|
123
|
-
.map((item) => renderPortableType(item, typeParametersInScope))
|
|
296
|
+
.map((item) => renderPortableType(item, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases))
|
|
124
297
|
.join(" & ");
|
|
125
298
|
case "dictionaryType":
|
|
126
|
-
return `Record<${renderPortableType(type.keyType, typeParametersInScope)}, ${renderPortableType(type.valueType, typeParametersInScope)}>`;
|
|
299
|
+
return `Record<${renderPortableType(type.keyType, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases)}, ${renderPortableType(type.valueType, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases)}>`;
|
|
127
300
|
case "functionType":
|
|
128
301
|
return `(${type.parameters
|
|
129
302
|
.map((parameter, index) => {
|
|
130
303
|
const parameterName = parameter.pattern.kind === "identifierPattern"
|
|
131
304
|
? parameter.pattern.name
|
|
132
305
|
: `p${index + 1}`;
|
|
133
|
-
return `${parameterName}: ${renderPortableType(parameter.type, typeParametersInScope)}`;
|
|
306
|
+
return `${parameterName}: ${renderPortableType(parameter.type, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases)}`;
|
|
134
307
|
})
|
|
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
|
-
}
|
|
308
|
+
.join(", ")}) => ${renderPortableType(type.returnType, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases)}`;
|
|
158
309
|
default:
|
|
159
|
-
return
|
|
310
|
+
return renderPortableShapeType(type, typeParametersInScope);
|
|
160
311
|
}
|
|
161
312
|
};
|
|
162
|
-
const renderUnknownParameters = (parameters, typeParametersInScope) => {
|
|
313
|
+
const renderUnknownParameters = (parameters, typeParametersInScope, localTypeNameRemaps = new Map(), anonymousStructuralAliases = new Map()) => {
|
|
163
314
|
return parameters
|
|
164
315
|
.map((parameter, index) => {
|
|
165
316
|
const baseName = parameter.pattern.kind === "identifierPattern"
|
|
@@ -167,7 +318,7 @@ const renderUnknownParameters = (parameters, typeParametersInScope) => {
|
|
|
167
318
|
: `p${index + 1}`;
|
|
168
319
|
const restPrefix = parameter.isRest ? "..." : "";
|
|
169
320
|
const optionalMark = parameter.isOptional && !parameter.isRest ? "?" : "";
|
|
170
|
-
const parameterType = renderPortableType(parameter.type, typeParametersInScope);
|
|
321
|
+
const parameterType = renderPortableType(parameter.type, typeParametersInScope, localTypeNameRemaps, anonymousStructuralAliases);
|
|
171
322
|
const typeSuffix = parameter.isRest
|
|
172
323
|
? `${parameterType}[]`
|
|
173
324
|
: parameterType;
|
|
@@ -175,13 +326,397 @@ const renderUnknownParameters = (parameters, typeParametersInScope) => {
|
|
|
175
326
|
})
|
|
176
327
|
.join(", ");
|
|
177
328
|
};
|
|
178
|
-
const renderMethodSignature = (name, typeParameters, parameters, returnType) => {
|
|
329
|
+
const renderMethodSignature = (name, typeParameters, parameters, returnType, localTypeNameRemaps = new Map(), anonymousStructuralAliases = new Map()) => {
|
|
179
330
|
const typeParametersText = printTypeParameters(typeParameters);
|
|
180
331
|
const typeParameterNames = typeParameters?.map((typeParameter) => typeParameter.name) ?? [];
|
|
181
|
-
const parametersText = renderUnknownParameters(parameters, typeParameterNames);
|
|
182
|
-
const returnTypeText = renderPortableType(returnType, typeParameterNames);
|
|
332
|
+
const parametersText = renderUnknownParameters(parameters, typeParameterNames, localTypeNameRemaps, anonymousStructuralAliases);
|
|
333
|
+
const returnTypeText = renderPortableType(returnType, typeParameterNames, localTypeNameRemaps, anonymousStructuralAliases);
|
|
183
334
|
return `${name}${typeParametersText}(${parametersText}): ${returnTypeText};`;
|
|
184
335
|
};
|
|
336
|
+
const renderSourceTypeNodeForAliasLookup = (node, localTypeNameRemaps) => {
|
|
337
|
+
switch (node.kind) {
|
|
338
|
+
case ts.SyntaxKind.StringKeyword:
|
|
339
|
+
return "string";
|
|
340
|
+
case ts.SyntaxKind.NumberKeyword:
|
|
341
|
+
return "number";
|
|
342
|
+
case ts.SyntaxKind.BooleanKeyword:
|
|
343
|
+
return "boolean";
|
|
344
|
+
case ts.SyntaxKind.VoidKeyword:
|
|
345
|
+
return "void";
|
|
346
|
+
case ts.SyntaxKind.NeverKeyword:
|
|
347
|
+
return "never";
|
|
348
|
+
case ts.SyntaxKind.UnknownKeyword:
|
|
349
|
+
return "unknown";
|
|
350
|
+
case ts.SyntaxKind.AnyKeyword:
|
|
351
|
+
return "unknown";
|
|
352
|
+
case ts.SyntaxKind.NullKeyword:
|
|
353
|
+
return "null";
|
|
354
|
+
case ts.SyntaxKind.UndefinedKeyword:
|
|
355
|
+
return "undefined";
|
|
356
|
+
}
|
|
357
|
+
if (ts.isParenthesizedTypeNode(node)) {
|
|
358
|
+
return `(${renderSourceTypeNodeForAliasLookup(node.type, localTypeNameRemaps)})`;
|
|
359
|
+
}
|
|
360
|
+
if (ts.isArrayTypeNode(node)) {
|
|
361
|
+
return `${renderSourceTypeNodeForAliasLookup(node.elementType, localTypeNameRemaps)}[]`;
|
|
362
|
+
}
|
|
363
|
+
if (ts.isTupleTypeNode(node)) {
|
|
364
|
+
return `[${node.elements
|
|
365
|
+
.map((element) => renderSourceTypeNodeForAliasLookup(element, localTypeNameRemaps))
|
|
366
|
+
.join(", ")}]`;
|
|
367
|
+
}
|
|
368
|
+
if (ts.isUnionTypeNode(node)) {
|
|
369
|
+
return node.types
|
|
370
|
+
.map((part) => renderSourceTypeNodeForAliasLookup(part, localTypeNameRemaps))
|
|
371
|
+
.join(" | ");
|
|
372
|
+
}
|
|
373
|
+
if (ts.isIntersectionTypeNode(node)) {
|
|
374
|
+
return node.types
|
|
375
|
+
.map((part) => renderSourceTypeNodeForAliasLookup(part, localTypeNameRemaps))
|
|
376
|
+
.join(" & ");
|
|
377
|
+
}
|
|
378
|
+
if (ts.isLiteralTypeNode(node)) {
|
|
379
|
+
return node.getText();
|
|
380
|
+
}
|
|
381
|
+
if (ts.isTypeReferenceNode(node)) {
|
|
382
|
+
const typeNameText = node.typeName.getText();
|
|
383
|
+
const rewrittenTypeName = rewriteSourceTypeText(typeNameText, localTypeNameRemaps);
|
|
384
|
+
if (!node.typeArguments || node.typeArguments.length === 0) {
|
|
385
|
+
return rewrittenTypeName;
|
|
386
|
+
}
|
|
387
|
+
return `${rewrittenTypeName}<${node.typeArguments
|
|
388
|
+
.map((argument) => renderSourceTypeNodeForAliasLookup(argument, localTypeNameRemaps))
|
|
389
|
+
.join(", ")}>`;
|
|
390
|
+
}
|
|
391
|
+
if (ts.isTypeLiteralNode(node)) {
|
|
392
|
+
return `{ ${node.members
|
|
393
|
+
.flatMap((member) => {
|
|
394
|
+
if (ts.isPropertySignature(member)) {
|
|
395
|
+
const propertyName = ts.isIdentifier(member.name)
|
|
396
|
+
? member.name.text
|
|
397
|
+
: ts.isStringLiteral(member.name)
|
|
398
|
+
? member.name.text
|
|
399
|
+
: undefined;
|
|
400
|
+
if (!propertyName || !member.type)
|
|
401
|
+
return [];
|
|
402
|
+
const readonlyMark = member.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ReadonlyKeyword) ?? false
|
|
403
|
+
? "readonly "
|
|
404
|
+
: "";
|
|
405
|
+
const propertyTypeText = member.questionToken
|
|
406
|
+
? ensureUndefinedInType(renderSourceTypeNodeForAliasLookup(member.type, localTypeNameRemaps))
|
|
407
|
+
: renderSourceTypeNodeForAliasLookup(member.type, localTypeNameRemaps);
|
|
408
|
+
return [
|
|
409
|
+
`${readonlyMark}${propertyName}: ${propertyTypeText}`,
|
|
410
|
+
];
|
|
411
|
+
}
|
|
412
|
+
if (ts.isMethodSignature(member)) {
|
|
413
|
+
const methodName = ts.isIdentifier(member.name)
|
|
414
|
+
? member.name.text
|
|
415
|
+
: ts.isStringLiteral(member.name)
|
|
416
|
+
? member.name.text
|
|
417
|
+
: undefined;
|
|
418
|
+
if (!methodName)
|
|
419
|
+
return [];
|
|
420
|
+
const typeParametersText = member.typeParameters
|
|
421
|
+
? `<${member.typeParameters
|
|
422
|
+
.map((typeParameter) => typeParameter.name.text)
|
|
423
|
+
.join(", ")}>`
|
|
424
|
+
: "";
|
|
425
|
+
const parametersText = member.parameters
|
|
426
|
+
.map((parameter, index) => {
|
|
427
|
+
const parameterName = ts.isIdentifier(parameter.name)
|
|
428
|
+
? parameter.name.text
|
|
429
|
+
: `p${index + 1}`;
|
|
430
|
+
const optionalMark = parameter.questionToken ? "?" : "";
|
|
431
|
+
const restPrefix = parameter.dotDotDotToken ? "..." : "";
|
|
432
|
+
const parameterType = parameter.type
|
|
433
|
+
? renderSourceTypeNodeForAliasLookup(parameter.type, localTypeNameRemaps)
|
|
434
|
+
: "unknown";
|
|
435
|
+
return `${restPrefix}${parameterName}${optionalMark}: ${parameterType}`;
|
|
436
|
+
})
|
|
437
|
+
.join(", ");
|
|
438
|
+
const returnType = member.type
|
|
439
|
+
? renderSourceTypeNodeForAliasLookup(member.type, localTypeNameRemaps)
|
|
440
|
+
: "void";
|
|
441
|
+
return [`${methodName}${typeParametersText}(${parametersText}): ${returnType}`];
|
|
442
|
+
}
|
|
443
|
+
return [];
|
|
444
|
+
})
|
|
445
|
+
.join("; ")} }`;
|
|
446
|
+
}
|
|
447
|
+
return node.getText();
|
|
448
|
+
};
|
|
449
|
+
const rewriteSourceTypeText = (typeText, localTypeNameRemaps, anonymousStructuralAliases = new Map()) => {
|
|
450
|
+
const sourceFile = ts.createSourceFile("__tsonic_source_type__.ts", `type __T = ${typeText};`, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
451
|
+
const statement = sourceFile.statements[0];
|
|
452
|
+
if (!statement || !ts.isTypeAliasDeclaration(statement))
|
|
453
|
+
return typeText;
|
|
454
|
+
const transformer = (context) => {
|
|
455
|
+
const visit = (node) => {
|
|
456
|
+
if (ts.isTypeReferenceNode(node) && ts.isIdentifier(node.typeName)) {
|
|
457
|
+
const remappedName = localTypeNameRemaps.get(node.typeName.text);
|
|
458
|
+
if (remappedName) {
|
|
459
|
+
return ts.factory.updateTypeReferenceNode(node, ts.factory.createIdentifier(remappedName), node.typeArguments);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
if (anonymousStructuralAliases.size > 0 && ts.isTypeLiteralNode(node)) {
|
|
463
|
+
const alias = anonymousStructuralAliases.get(renderSourceTypeNodeForAliasLookup(node, localTypeNameRemaps));
|
|
464
|
+
if (alias) {
|
|
465
|
+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(alias.name), alias.typeParameters.map((typeParameter) => ts.factory.createTypeReferenceNode(typeParameter)));
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
return ts.visitEachChild(node, visit, context);
|
|
469
|
+
};
|
|
470
|
+
return (node) => ts.visitNode(node, visit);
|
|
471
|
+
};
|
|
472
|
+
const transformed = ts.transform(statement.type, [transformer]).transformed[0];
|
|
473
|
+
if (!transformed)
|
|
474
|
+
return typeText;
|
|
475
|
+
const printer = ts.createPrinter({ removeComments: true });
|
|
476
|
+
return printer.printNode(ts.EmitHint.Unspecified, transformed, sourceFile);
|
|
477
|
+
};
|
|
478
|
+
const selectPreferredSourceFunctionSignature = (opts) => {
|
|
479
|
+
const targetTypeParameterCount = opts.declaration.typeParameters?.length ?? 0;
|
|
480
|
+
const targetParameterCount = opts.declaration.parameters.length;
|
|
481
|
+
const exact = opts.sourceSignatures.find((signature) => {
|
|
482
|
+
return (signature.parameters.length === targetParameterCount &&
|
|
483
|
+
signature.typeParameterCount === targetTypeParameterCount);
|
|
484
|
+
});
|
|
485
|
+
return exact ?? opts.sourceSignatures[0];
|
|
486
|
+
};
|
|
487
|
+
const renderSourceFunctionSignature = (opts) => {
|
|
488
|
+
const sourceSignature = selectPreferredSourceFunctionSignature({
|
|
489
|
+
declaration: opts.declaration,
|
|
490
|
+
sourceSignatures: opts.sourceSignatures,
|
|
491
|
+
});
|
|
492
|
+
if (!sourceSignature)
|
|
493
|
+
return undefined;
|
|
494
|
+
const parametersText = sourceSignature.parameters
|
|
495
|
+
.map((parameter) => `${parameter.prefixText}${rewriteSourceTypeText(parameter.typeText, opts.localTypeNameRemaps, opts.anonymousStructuralAliases)}`)
|
|
496
|
+
.join(", ");
|
|
497
|
+
return {
|
|
498
|
+
typeParametersText: sourceSignature.typeParametersText,
|
|
499
|
+
parametersText,
|
|
500
|
+
returnTypeText: rewriteSourceTypeText(sourceSignature.returnTypeText, opts.localTypeNameRemaps, opts.anonymousStructuralAliases),
|
|
501
|
+
};
|
|
502
|
+
};
|
|
503
|
+
const renderSourceValueType = (sourceType, localTypeNameRemaps, anonymousStructuralAliases = new Map()) => !sourceType
|
|
504
|
+
? undefined
|
|
505
|
+
: rewriteSourceTypeText(sourceType.typeText, localTypeNameRemaps, anonymousStructuralAliases);
|
|
506
|
+
const renderSourceFunctionType = (opts) => {
|
|
507
|
+
const sourceSignature = opts.sourceSignatures[0];
|
|
508
|
+
if (!sourceSignature)
|
|
509
|
+
return undefined;
|
|
510
|
+
const parametersText = sourceSignature.parameters
|
|
511
|
+
.map((parameter) => `${parameter.prefixText}${rewriteSourceTypeText(parameter.typeText, opts.localTypeNameRemaps, opts.anonymousStructuralAliases)}`)
|
|
512
|
+
.join(", ");
|
|
513
|
+
return `${sourceSignature.typeParametersText}(${parametersText}) => ${rewriteSourceTypeText(sourceSignature.returnTypeText, opts.localTypeNameRemaps, opts.anonymousStructuralAliases)}`;
|
|
514
|
+
};
|
|
515
|
+
const isGeneratedStructuralHelperName = (name) => name.startsWith("__Anon_") || /__\d+$/.test(name);
|
|
516
|
+
const buildAnonymousStructuralAliasMap = (plan) => {
|
|
517
|
+
const aliases = new Map();
|
|
518
|
+
const registerAnonymousClass = (localName, declaration) => {
|
|
519
|
+
if (!isGeneratedStructuralHelperName(localName))
|
|
520
|
+
return;
|
|
521
|
+
const members = [];
|
|
522
|
+
for (const member of declaration.members) {
|
|
523
|
+
if (member.kind === "propertyDeclaration") {
|
|
524
|
+
if (isPortableMarkerMemberName(member.name))
|
|
525
|
+
continue;
|
|
526
|
+
members.push({
|
|
527
|
+
kind: "propertySignature",
|
|
528
|
+
name: member.name,
|
|
529
|
+
type: member.type ?? { kind: "unknownType" },
|
|
530
|
+
isOptional: false,
|
|
531
|
+
isReadonly: member.isReadonly,
|
|
532
|
+
});
|
|
533
|
+
continue;
|
|
534
|
+
}
|
|
535
|
+
if (member.kind === "methodDeclaration") {
|
|
536
|
+
if (isPortableMarkerMemberName(member.name))
|
|
537
|
+
continue;
|
|
538
|
+
members.push({
|
|
539
|
+
kind: "methodSignature",
|
|
540
|
+
name: member.name,
|
|
541
|
+
parameters: member.parameters,
|
|
542
|
+
returnType: member.returnType,
|
|
543
|
+
typeParameters: member.typeParameters,
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
const shape = renderPortableType({ kind: "objectType", members }, declaration.typeParameters?.map((typeParameter) => typeParameter.name) ?? [], new Map(), new Map());
|
|
548
|
+
const existing = aliases.get(shape) ?? [];
|
|
549
|
+
existing.push({
|
|
550
|
+
name: localName,
|
|
551
|
+
typeParameters: declaration.typeParameters?.map((typeParameter) => typeParameter.name) ??
|
|
552
|
+
[],
|
|
553
|
+
});
|
|
554
|
+
aliases.set(shape, existing);
|
|
555
|
+
};
|
|
556
|
+
for (const symbol of plan.typeDeclarations) {
|
|
557
|
+
if (symbol.kind !== "class" || symbol.declaration.kind !== "classDeclaration") {
|
|
558
|
+
continue;
|
|
559
|
+
}
|
|
560
|
+
registerAnonymousClass(symbol.localName, symbol.declaration);
|
|
561
|
+
}
|
|
562
|
+
for (const helper of plan.internalHelperTypeDeclarations) {
|
|
563
|
+
if (helper.kind !== "class")
|
|
564
|
+
continue;
|
|
565
|
+
registerAnonymousClass(helper.emittedName, helper.declaration);
|
|
566
|
+
}
|
|
567
|
+
const uniqueAliases = new Map();
|
|
568
|
+
for (const [shape, candidates] of aliases.entries()) {
|
|
569
|
+
if (candidates.length !== 1)
|
|
570
|
+
continue;
|
|
571
|
+
const onlyCandidate = candidates[0];
|
|
572
|
+
if (!onlyCandidate)
|
|
573
|
+
continue;
|
|
574
|
+
uniqueAliases.set(shape, onlyCandidate);
|
|
575
|
+
}
|
|
576
|
+
return uniqueAliases;
|
|
577
|
+
};
|
|
578
|
+
const collectReferencedPortableTypeNames = (type, typeParametersInScope, out) => {
|
|
579
|
+
if (!type)
|
|
580
|
+
return;
|
|
581
|
+
switch (type.kind) {
|
|
582
|
+
case "primitiveType":
|
|
583
|
+
case "literalType":
|
|
584
|
+
case "voidType":
|
|
585
|
+
case "neverType":
|
|
586
|
+
case "unknownType":
|
|
587
|
+
case "anyType":
|
|
588
|
+
return;
|
|
589
|
+
case "typeParameterType":
|
|
590
|
+
if (!typeParametersInScope.has(type.name)) {
|
|
591
|
+
out.add(type.name);
|
|
592
|
+
}
|
|
593
|
+
return;
|
|
594
|
+
case "arrayType":
|
|
595
|
+
collectReferencedPortableTypeNames(type.elementType, typeParametersInScope, out);
|
|
596
|
+
return;
|
|
597
|
+
case "tupleType":
|
|
598
|
+
for (const element of type.elementTypes) {
|
|
599
|
+
collectReferencedPortableTypeNames(element, typeParametersInScope, out);
|
|
600
|
+
}
|
|
601
|
+
return;
|
|
602
|
+
case "unionType":
|
|
603
|
+
case "intersectionType":
|
|
604
|
+
for (const member of type.types) {
|
|
605
|
+
collectReferencedPortableTypeNames(member, typeParametersInScope, out);
|
|
606
|
+
}
|
|
607
|
+
return;
|
|
608
|
+
case "dictionaryType":
|
|
609
|
+
collectReferencedPortableTypeNames(type.keyType, typeParametersInScope, out);
|
|
610
|
+
collectReferencedPortableTypeNames(type.valueType, typeParametersInScope, out);
|
|
611
|
+
return;
|
|
612
|
+
case "functionType":
|
|
613
|
+
for (const parameter of type.parameters) {
|
|
614
|
+
collectReferencedPortableTypeNames(parameter.type, typeParametersInScope, out);
|
|
615
|
+
}
|
|
616
|
+
collectReferencedPortableTypeNames(type.returnType, typeParametersInScope, out);
|
|
617
|
+
return;
|
|
618
|
+
case "objectType":
|
|
619
|
+
for (const member of type.members) {
|
|
620
|
+
if (member.kind === "propertySignature") {
|
|
621
|
+
collectReferencedPortableTypeNames(member.type, typeParametersInScope, out);
|
|
622
|
+
continue;
|
|
623
|
+
}
|
|
624
|
+
const nestedTypeParameters = new Set(typeParametersInScope);
|
|
625
|
+
for (const typeParameter of member.typeParameters ?? []) {
|
|
626
|
+
nestedTypeParameters.add(typeParameter.name);
|
|
627
|
+
}
|
|
628
|
+
for (const parameter of member.parameters) {
|
|
629
|
+
collectReferencedPortableTypeNames(parameter.type, nestedTypeParameters, out);
|
|
630
|
+
}
|
|
631
|
+
collectReferencedPortableTypeNames(member.returnType, nestedTypeParameters, out);
|
|
632
|
+
}
|
|
633
|
+
return;
|
|
634
|
+
case "referenceType":
|
|
635
|
+
out.add(renderReferenceType(type.name, type.typeArguments, []).split("<")[0]);
|
|
636
|
+
for (const typeArgument of type.typeArguments ?? []) {
|
|
637
|
+
collectReferencedPortableTypeNames(typeArgument, typeParametersInScope, out);
|
|
638
|
+
}
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
};
|
|
642
|
+
const collectReferencedPortableTypesFromParameters = (parameters, typeParametersInScope, out) => {
|
|
643
|
+
for (const parameter of parameters) {
|
|
644
|
+
collectReferencedPortableTypeNames(parameter.type, typeParametersInScope, out);
|
|
645
|
+
}
|
|
646
|
+
};
|
|
647
|
+
const collectReferencedPortableTypeNamesFromDeclaration = (declaration, out) => {
|
|
648
|
+
switch (declaration.kind) {
|
|
649
|
+
case "enumDeclaration":
|
|
650
|
+
return;
|
|
651
|
+
case "typeAliasDeclaration": {
|
|
652
|
+
const typeParametersInScope = new Set((declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name));
|
|
653
|
+
collectReferencedPortableTypeNames(declaration.type, typeParametersInScope, out);
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
case "interfaceDeclaration": {
|
|
657
|
+
const typeParametersInScope = new Set((declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name));
|
|
658
|
+
for (const baseType of declaration.extends) {
|
|
659
|
+
collectReferencedPortableTypeNames(baseType, typeParametersInScope, out);
|
|
660
|
+
}
|
|
661
|
+
for (const member of declaration.members) {
|
|
662
|
+
if (member.kind === "propertySignature") {
|
|
663
|
+
collectReferencedPortableTypeNames(member.type, typeParametersInScope, out);
|
|
664
|
+
continue;
|
|
665
|
+
}
|
|
666
|
+
const nestedTypeParameters = new Set(typeParametersInScope);
|
|
667
|
+
for (const typeParameter of member.typeParameters ?? []) {
|
|
668
|
+
nestedTypeParameters.add(typeParameter.name);
|
|
669
|
+
}
|
|
670
|
+
collectReferencedPortableTypesFromParameters(member.parameters, nestedTypeParameters, out);
|
|
671
|
+
collectReferencedPortableTypeNames(member.returnType, nestedTypeParameters, out);
|
|
672
|
+
}
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
case "classDeclaration": {
|
|
676
|
+
const typeParametersInScope = new Set((declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name));
|
|
677
|
+
if (declaration.superClass) {
|
|
678
|
+
collectReferencedPortableTypeNames(declaration.superClass, typeParametersInScope, out);
|
|
679
|
+
}
|
|
680
|
+
for (const implementedType of declaration.implements) {
|
|
681
|
+
collectReferencedPortableTypeNames(implementedType, typeParametersInScope, out);
|
|
682
|
+
}
|
|
683
|
+
for (const member of declaration.members) {
|
|
684
|
+
switch (member.kind) {
|
|
685
|
+
case "constructorDeclaration":
|
|
686
|
+
collectReferencedPortableTypesFromParameters(member.parameters, typeParametersInScope, out);
|
|
687
|
+
continue;
|
|
688
|
+
case "propertyDeclaration":
|
|
689
|
+
collectReferencedPortableTypeNames(member.type, typeParametersInScope, out);
|
|
690
|
+
continue;
|
|
691
|
+
case "methodDeclaration": {
|
|
692
|
+
const nestedTypeParameters = new Set(typeParametersInScope);
|
|
693
|
+
for (const typeParameter of member.typeParameters ?? []) {
|
|
694
|
+
nestedTypeParameters.add(typeParameter.name);
|
|
695
|
+
}
|
|
696
|
+
collectReferencedPortableTypesFromParameters(member.parameters, nestedTypeParameters, out);
|
|
697
|
+
collectReferencedPortableTypeNames(member.returnType, nestedTypeParameters, out);
|
|
698
|
+
continue;
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
return;
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
};
|
|
706
|
+
const classifyLocalTypeDeclarationKind = (statement) => {
|
|
707
|
+
switch (statement.kind) {
|
|
708
|
+
case "classDeclaration":
|
|
709
|
+
return "class";
|
|
710
|
+
case "interfaceDeclaration":
|
|
711
|
+
return "interface";
|
|
712
|
+
case "enumDeclaration":
|
|
713
|
+
return "enum";
|
|
714
|
+
case "typeAliasDeclaration":
|
|
715
|
+
return "typeAlias";
|
|
716
|
+
default:
|
|
717
|
+
return undefined;
|
|
718
|
+
}
|
|
719
|
+
};
|
|
185
720
|
const declarationNameOf = (statement) => {
|
|
186
721
|
switch (statement.kind) {
|
|
187
722
|
case "functionDeclaration":
|
|
@@ -328,6 +863,22 @@ const collectModuleExports = (module, modulesByFileKey) => {
|
|
|
328
863
|
value: exportedSymbols.sort((left, right) => left.exportName.localeCompare(right.exportName)),
|
|
329
864
|
};
|
|
330
865
|
};
|
|
866
|
+
const finalizeCrossNamespaceReexports = (grouped) => {
|
|
867
|
+
const dtsStatements = [];
|
|
868
|
+
const jsValueStatements = [];
|
|
869
|
+
for (const [key, specs] of Array.from(grouped.entries()).sort((a, b) => a[0].localeCompare(b[0]))) {
|
|
870
|
+
const [moduleSpecifier, kind] = key.split("|");
|
|
871
|
+
const unique = Array.from(new Set(specs)).sort((a, b) => a.localeCompare(b));
|
|
872
|
+
if (kind === "type") {
|
|
873
|
+
dtsStatements.push(`export type { ${unique.join(", ")} } from '${moduleSpecifier}';`);
|
|
874
|
+
continue;
|
|
875
|
+
}
|
|
876
|
+
const statement = `export { ${unique.join(", ")} } from '${moduleSpecifier}';`;
|
|
877
|
+
dtsStatements.push(statement);
|
|
878
|
+
jsValueStatements.push(statement);
|
|
879
|
+
}
|
|
880
|
+
return { dtsStatements, jsValueStatements };
|
|
881
|
+
};
|
|
331
882
|
const moduleNamespacePath = (namespace) => {
|
|
332
883
|
return namespace.length > 0 ? namespace : "index";
|
|
333
884
|
};
|
|
@@ -512,27 +1063,62 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
|
|
|
512
1063
|
const wrapperImportsByLocalName = new Map();
|
|
513
1064
|
const typeImportsByLocalName = new Map();
|
|
514
1065
|
const typeAliasesByName = new Map();
|
|
1066
|
+
const exportedTypeDeclarationNames = new Set();
|
|
515
1067
|
const exportedFunctionSignaturesByName = new Map();
|
|
1068
|
+
const exportedValueTypesByName = new Map();
|
|
516
1069
|
const memberTypesByClassAndMember = new Map();
|
|
1070
|
+
const anonymousTypeLiteralsByShape = new Map();
|
|
517
1071
|
const printTypeParametersText = (typeParameters) => {
|
|
518
1072
|
if (!typeParameters || typeParameters.length === 0)
|
|
519
1073
|
return "";
|
|
520
1074
|
return `<${typeParameters.map((tp) => tp.getText(sourceFile)).join(", ")}>`;
|
|
521
1075
|
};
|
|
522
|
-
const
|
|
1076
|
+
const printParameterSignature = (param) => {
|
|
523
1077
|
const rest = param.dotDotDotToken ? "..." : "";
|
|
524
1078
|
const name = param.name.getText(sourceFile);
|
|
525
1079
|
const optional = param.questionToken ? "?" : "";
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
: "unknown"
|
|
529
|
-
|
|
1080
|
+
return {
|
|
1081
|
+
prefixText: `${rest}${name}${optional}: `,
|
|
1082
|
+
typeText: param.type ? printTypeNodeText(param.type, sourceFile) : "unknown",
|
|
1083
|
+
};
|
|
530
1084
|
};
|
|
531
1085
|
const addExportedFunctionSignature = (name, signature) => {
|
|
532
1086
|
const signatures = exportedFunctionSignaturesByName.get(name) ?? [];
|
|
533
1087
|
signatures.push(signature);
|
|
534
1088
|
exportedFunctionSignaturesByName.set(name, signatures);
|
|
535
1089
|
};
|
|
1090
|
+
const registerAnonymousTypeLiteralsInTypeNode = (typeNode) => {
|
|
1091
|
+
if (!typeNode)
|
|
1092
|
+
return;
|
|
1093
|
+
const visit = (current) => {
|
|
1094
|
+
if (ts.isTypeLiteralNode(current)) {
|
|
1095
|
+
const shape = renderSourceTypeNodeForAliasLookup(current, new Map());
|
|
1096
|
+
if (!anonymousTypeLiteralsByShape.has(shape)) {
|
|
1097
|
+
const members = new Map();
|
|
1098
|
+
for (const member of current.members) {
|
|
1099
|
+
if (!ts.isPropertySignature(member))
|
|
1100
|
+
continue;
|
|
1101
|
+
if (!member.name || !member.type)
|
|
1102
|
+
continue;
|
|
1103
|
+
const memberName = getPropertyNameText(member.name);
|
|
1104
|
+
if (!memberName)
|
|
1105
|
+
continue;
|
|
1106
|
+
members.set(memberName, {
|
|
1107
|
+
typeNode: member.type,
|
|
1108
|
+
typeText: printTypeNodeText(member.type, sourceFile),
|
|
1109
|
+
isOptional: member.questionToken !== undefined,
|
|
1110
|
+
});
|
|
1111
|
+
}
|
|
1112
|
+
anonymousTypeLiteralsByShape.set(shape, {
|
|
1113
|
+
typeText: printTypeNodeText(current, sourceFile),
|
|
1114
|
+
members,
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
ts.forEachChild(current, visit);
|
|
1119
|
+
};
|
|
1120
|
+
visit(typeNode);
|
|
1121
|
+
};
|
|
536
1122
|
for (const stmt of sourceFile.statements) {
|
|
537
1123
|
if (ts.isImportDeclaration(stmt)) {
|
|
538
1124
|
const moduleSpecifier = ts.isStringLiteral(stmt.moduleSpecifier)
|
|
@@ -549,9 +1135,6 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
|
|
|
549
1135
|
for (const spec of namedBindings.elements) {
|
|
550
1136
|
const localName = spec.name.text;
|
|
551
1137
|
const importedName = (spec.propertyName ?? spec.name).text;
|
|
552
|
-
const isTypeOnly = clause.isTypeOnly || spec.isTypeOnly;
|
|
553
|
-
if (!isTypeOnly)
|
|
554
|
-
continue;
|
|
555
1138
|
typeImportsByLocalName.set(localName, {
|
|
556
1139
|
source: moduleSpecifier,
|
|
557
1140
|
importedName,
|
|
@@ -567,6 +1150,7 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
|
|
|
567
1150
|
}
|
|
568
1151
|
if (ts.isTypeAliasDeclaration(stmt)) {
|
|
569
1152
|
const aliasName = stmt.name.text;
|
|
1153
|
+
const hasExport = stmt.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
|
|
570
1154
|
const typeParameterNames = (stmt.typeParameters ?? []).map((tp) => tp.name.text);
|
|
571
1155
|
typeAliasesByName.set(aliasName, {
|
|
572
1156
|
typeParametersText: printTypeParametersText(stmt.typeParameters),
|
|
@@ -574,16 +1158,25 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
|
|
|
574
1158
|
type: stmt.type,
|
|
575
1159
|
typeText: printTypeNodeText(stmt.type, sourceFile),
|
|
576
1160
|
});
|
|
1161
|
+
registerAnonymousTypeLiteralsInTypeNode(stmt.type);
|
|
1162
|
+
if (hasExport) {
|
|
1163
|
+
exportedTypeDeclarationNames.add(aliasName);
|
|
1164
|
+
}
|
|
577
1165
|
continue;
|
|
578
1166
|
}
|
|
579
1167
|
if (ts.isFunctionDeclaration(stmt)) {
|
|
580
1168
|
const hasExport = stmt.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
|
|
581
1169
|
if (!hasExport || !stmt.name || !stmt.type)
|
|
582
1170
|
continue;
|
|
583
|
-
const
|
|
1171
|
+
for (const parameter of stmt.parameters) {
|
|
1172
|
+
registerAnonymousTypeLiteralsInTypeNode(parameter.type);
|
|
1173
|
+
}
|
|
1174
|
+
registerAnonymousTypeLiteralsInTypeNode(stmt.type);
|
|
1175
|
+
const parameters = stmt.parameters.map(printParameterSignature);
|
|
584
1176
|
addExportedFunctionSignature(stmt.name.text, {
|
|
585
1177
|
typeParametersText: printTypeParametersText(stmt.typeParameters),
|
|
586
|
-
|
|
1178
|
+
typeParameterCount: stmt.typeParameters?.length ?? 0,
|
|
1179
|
+
parameters,
|
|
587
1180
|
returnTypeText: printTypeNodeText(stmt.type, sourceFile),
|
|
588
1181
|
});
|
|
589
1182
|
continue;
|
|
@@ -601,16 +1194,25 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
|
|
|
601
1194
|
continue;
|
|
602
1195
|
if (!ts.isArrowFunction(initializer) &&
|
|
603
1196
|
!ts.isFunctionExpression(initializer)) {
|
|
1197
|
+
if (declaration.type) {
|
|
1198
|
+
registerAnonymousTypeLiteralsInTypeNode(declaration.type);
|
|
1199
|
+
exportedValueTypesByName.set(exportName, {
|
|
1200
|
+
typeText: printTypeNodeText(declaration.type, sourceFile),
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
604
1203
|
continue;
|
|
605
1204
|
}
|
|
606
1205
|
if (!initializer.type)
|
|
607
1206
|
continue;
|
|
608
|
-
const
|
|
609
|
-
.
|
|
610
|
-
|
|
1207
|
+
for (const parameter of initializer.parameters) {
|
|
1208
|
+
registerAnonymousTypeLiteralsInTypeNode(parameter.type);
|
|
1209
|
+
}
|
|
1210
|
+
registerAnonymousTypeLiteralsInTypeNode(initializer.type);
|
|
1211
|
+
const parameters = initializer.parameters.map(printParameterSignature);
|
|
611
1212
|
addExportedFunctionSignature(exportName, {
|
|
612
1213
|
typeParametersText: printTypeParametersText(initializer.typeParameters),
|
|
613
|
-
|
|
1214
|
+
typeParameterCount: initializer.typeParameters?.length ?? 0,
|
|
1215
|
+
parameters,
|
|
614
1216
|
returnTypeText: printTypeNodeText(initializer.type, sourceFile),
|
|
615
1217
|
});
|
|
616
1218
|
}
|
|
@@ -618,6 +1220,10 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
|
|
|
618
1220
|
}
|
|
619
1221
|
if (ts.isClassDeclaration(stmt) && stmt.name) {
|
|
620
1222
|
const className = stmt.name.text;
|
|
1223
|
+
const hasExport = stmt.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
|
|
1224
|
+
if (hasExport) {
|
|
1225
|
+
exportedTypeDeclarationNames.add(className);
|
|
1226
|
+
}
|
|
621
1227
|
const members = memberTypesByClassAndMember.get(className) ??
|
|
622
1228
|
new Map();
|
|
623
1229
|
for (const member of stmt.members) {
|
|
@@ -640,6 +1246,7 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
|
|
|
640
1246
|
const name = getPropertyNameText(member.name);
|
|
641
1247
|
if (!name)
|
|
642
1248
|
continue;
|
|
1249
|
+
registerAnonymousTypeLiteralsInTypeNode(member.type);
|
|
643
1250
|
members.set(name, {
|
|
644
1251
|
typeNode: member.type,
|
|
645
1252
|
typeText: printTypeNodeText(member.type, sourceFile),
|
|
@@ -654,6 +1261,10 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
|
|
|
654
1261
|
}
|
|
655
1262
|
if (ts.isInterfaceDeclaration(stmt)) {
|
|
656
1263
|
const interfaceName = stmt.name.text;
|
|
1264
|
+
const hasExport = stmt.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
|
|
1265
|
+
if (hasExport) {
|
|
1266
|
+
exportedTypeDeclarationNames.add(interfaceName);
|
|
1267
|
+
}
|
|
657
1268
|
const members = memberTypesByClassAndMember.get(interfaceName) ??
|
|
658
1269
|
new Map();
|
|
659
1270
|
for (const member of stmt.members) {
|
|
@@ -664,6 +1275,7 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
|
|
|
664
1275
|
const name = getPropertyNameText(member.name);
|
|
665
1276
|
if (!name)
|
|
666
1277
|
continue;
|
|
1278
|
+
registerAnonymousTypeLiteralsInTypeNode(member.type);
|
|
667
1279
|
members.set(name, {
|
|
668
1280
|
typeNode: member.type,
|
|
669
1281
|
typeText: printTypeNodeText(member.type, sourceFile),
|
|
@@ -673,6 +1285,13 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
|
|
|
673
1285
|
if (members.size > 0) {
|
|
674
1286
|
memberTypesByClassAndMember.set(interfaceName, members);
|
|
675
1287
|
}
|
|
1288
|
+
continue;
|
|
1289
|
+
}
|
|
1290
|
+
if (ts.isEnumDeclaration(stmt)) {
|
|
1291
|
+
const hasExport = stmt.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
|
|
1292
|
+
if (hasExport) {
|
|
1293
|
+
exportedTypeDeclarationNames.add(stmt.name.text);
|
|
1294
|
+
}
|
|
676
1295
|
}
|
|
677
1296
|
}
|
|
678
1297
|
return {
|
|
@@ -682,8 +1301,11 @@ const buildModuleSourceIndex = (absoluteFilePath, fileKey) => {
|
|
|
682
1301
|
wrapperImportsByLocalName,
|
|
683
1302
|
typeImportsByLocalName,
|
|
684
1303
|
typeAliasesByName,
|
|
1304
|
+
exportedTypeDeclarationNames,
|
|
685
1305
|
exportedFunctionSignaturesByName,
|
|
1306
|
+
exportedValueTypesByName,
|
|
686
1307
|
memberTypesByClassAndMember,
|
|
1308
|
+
anonymousTypeLiteralsByShape,
|
|
687
1309
|
},
|
|
688
1310
|
};
|
|
689
1311
|
};
|
|
@@ -798,42 +1420,6 @@ const collectExtensionWrapperImportsFromSourceType = (opts) => {
|
|
|
798
1420
|
}
|
|
799
1421
|
return { ok: true, value: wrappers };
|
|
800
1422
|
};
|
|
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
1423
|
const moduleNamespaceToInternalSpecifier = (namespace) => {
|
|
838
1424
|
const nsPath = moduleNamespacePath(namespace);
|
|
839
1425
|
return `./${nsPath}/internal/index.js`;
|
|
@@ -842,6 +1428,10 @@ const toClrTypeName = (namespace, typeName, arity) => {
|
|
|
842
1428
|
const suffix = arity && arity > 0 ? `\`${arity}` : "";
|
|
843
1429
|
return `${namespace}.${typeName}${suffix}`;
|
|
844
1430
|
};
|
|
1431
|
+
const toBindingTypeAlias = (namespace, typeName, arity) => {
|
|
1432
|
+
const normalizedName = normalizeTypeReferenceName(typeName, arity);
|
|
1433
|
+
return namespace.length > 0 ? `${namespace}.${normalizedName}` : normalizedName;
|
|
1434
|
+
};
|
|
845
1435
|
const toStableId = (assemblyName, clrName) => {
|
|
846
1436
|
return `${assemblyName}:${clrName}`;
|
|
847
1437
|
};
|
|
@@ -870,7 +1460,111 @@ const isNumericValueType = (name) => {
|
|
|
870
1460
|
name === "System.Byte" ||
|
|
871
1461
|
name === "System.SByte");
|
|
872
1462
|
};
|
|
873
|
-
const
|
|
1463
|
+
const rewriteBindingSemanticParameter = (parameter, localTypeNameRemaps) => ({
|
|
1464
|
+
...parameter,
|
|
1465
|
+
type: rewriteBindingSemanticType(parameter.type, localTypeNameRemaps),
|
|
1466
|
+
});
|
|
1467
|
+
const rewriteBindingSemanticMember = (member, localTypeNameRemaps) => {
|
|
1468
|
+
if (member.kind === "propertySignature") {
|
|
1469
|
+
return {
|
|
1470
|
+
...member,
|
|
1471
|
+
type: rewriteBindingSemanticType(member.type, localTypeNameRemaps) ??
|
|
1472
|
+
member.type,
|
|
1473
|
+
};
|
|
1474
|
+
}
|
|
1475
|
+
return {
|
|
1476
|
+
...member,
|
|
1477
|
+
parameters: member.parameters.map((parameter) => rewriteBindingSemanticParameter(parameter, localTypeNameRemaps)),
|
|
1478
|
+
returnType: rewriteBindingSemanticType(member.returnType, localTypeNameRemaps) ??
|
|
1479
|
+
member.returnType,
|
|
1480
|
+
};
|
|
1481
|
+
};
|
|
1482
|
+
const rewriteBindingSemanticType = (type, localTypeNameRemaps) => {
|
|
1483
|
+
if (!type)
|
|
1484
|
+
return undefined;
|
|
1485
|
+
switch (type.kind) {
|
|
1486
|
+
case "referenceType": {
|
|
1487
|
+
const rewrittenName = normalizeTypeReferenceName(localTypeNameRemaps.get(type.name) ?? type.name, type.typeArguments?.length);
|
|
1488
|
+
return {
|
|
1489
|
+
...type,
|
|
1490
|
+
name: rewrittenName,
|
|
1491
|
+
typeArguments: type.typeArguments?.map((arg) => rewriteBindingSemanticType(arg, localTypeNameRemaps)),
|
|
1492
|
+
structuralMembers: type.structuralMembers?.map((member) => rewriteBindingSemanticMember(member, localTypeNameRemaps)),
|
|
1493
|
+
};
|
|
1494
|
+
}
|
|
1495
|
+
case "arrayType":
|
|
1496
|
+
return {
|
|
1497
|
+
...type,
|
|
1498
|
+
elementType: rewriteBindingSemanticType(type.elementType, localTypeNameRemaps) ??
|
|
1499
|
+
type.elementType,
|
|
1500
|
+
};
|
|
1501
|
+
case "tupleType":
|
|
1502
|
+
return {
|
|
1503
|
+
...type,
|
|
1504
|
+
elementTypes: type.elementTypes.map((elementType) => rewriteBindingSemanticType(elementType, localTypeNameRemaps)),
|
|
1505
|
+
};
|
|
1506
|
+
case "functionType":
|
|
1507
|
+
return {
|
|
1508
|
+
...type,
|
|
1509
|
+
parameters: type.parameters.map((parameter) => rewriteBindingSemanticParameter(parameter, localTypeNameRemaps)),
|
|
1510
|
+
returnType: rewriteBindingSemanticType(type.returnType, localTypeNameRemaps) ??
|
|
1511
|
+
type.returnType,
|
|
1512
|
+
};
|
|
1513
|
+
case "objectType":
|
|
1514
|
+
return {
|
|
1515
|
+
...type,
|
|
1516
|
+
members: type.members.map((member) => rewriteBindingSemanticMember(member, localTypeNameRemaps)),
|
|
1517
|
+
};
|
|
1518
|
+
case "dictionaryType":
|
|
1519
|
+
return {
|
|
1520
|
+
...type,
|
|
1521
|
+
keyType: rewriteBindingSemanticType(type.keyType, localTypeNameRemaps) ??
|
|
1522
|
+
type.keyType,
|
|
1523
|
+
valueType: rewriteBindingSemanticType(type.valueType, localTypeNameRemaps) ??
|
|
1524
|
+
type.valueType,
|
|
1525
|
+
};
|
|
1526
|
+
case "unionType":
|
|
1527
|
+
case "intersectionType":
|
|
1528
|
+
return {
|
|
1529
|
+
...type,
|
|
1530
|
+
types: type.types.map((candidate) => rewriteBindingSemanticType(candidate, localTypeNameRemaps)),
|
|
1531
|
+
};
|
|
1532
|
+
default:
|
|
1533
|
+
return type;
|
|
1534
|
+
}
|
|
1535
|
+
};
|
|
1536
|
+
const buildSemanticSignature = (opts) => {
|
|
1537
|
+
return {
|
|
1538
|
+
typeParameters: opts.typeParameters?.map((typeParameter) => typeParameter.name),
|
|
1539
|
+
parameters: opts.parameters.map((parameter) => rewriteBindingSemanticParameter(parameter, opts.localTypeNameRemaps)),
|
|
1540
|
+
returnType: rewriteBindingSemanticType(opts.returnType, opts.localTypeNameRemaps),
|
|
1541
|
+
};
|
|
1542
|
+
};
|
|
1543
|
+
const buildSemanticSignatureFromFunctionType = (type, localTypeNameRemaps) => ({
|
|
1544
|
+
typeParameters: undefined,
|
|
1545
|
+
parameters: type.parameters.map((parameter) => rewriteBindingSemanticParameter(parameter, localTypeNameRemaps)),
|
|
1546
|
+
returnType: rewriteBindingSemanticType(type.returnType, localTypeNameRemaps),
|
|
1547
|
+
});
|
|
1548
|
+
const resolveFunctionTypeFromValueDeclarator = (declarator) => {
|
|
1549
|
+
if (declarator?.type?.kind === "functionType") {
|
|
1550
|
+
return declarator.type;
|
|
1551
|
+
}
|
|
1552
|
+
const initializerType = declarator?.initializer?.inferredType;
|
|
1553
|
+
if (initializerType?.kind === "functionType") {
|
|
1554
|
+
return initializerType;
|
|
1555
|
+
}
|
|
1556
|
+
return undefined;
|
|
1557
|
+
};
|
|
1558
|
+
const areBindingSemanticSignaturesEqual = (left, right) => JSON.stringify(left ?? null) === JSON.stringify(right ?? null);
|
|
1559
|
+
const areBindingSemanticsEqual = (left, right) => left.kind === right.kind &&
|
|
1560
|
+
left.clrName === right.clrName &&
|
|
1561
|
+
left.declaringClrType === right.declaringClrType &&
|
|
1562
|
+
left.declaringAssemblyName === right.declaringAssemblyName &&
|
|
1563
|
+
left.semanticOptional === right.semanticOptional &&
|
|
1564
|
+
JSON.stringify(left.semanticType ?? null) ===
|
|
1565
|
+
JSON.stringify(right.semanticType ?? null) &&
|
|
1566
|
+
areBindingSemanticSignaturesEqual(left.semanticSignature, right.semanticSignature);
|
|
1567
|
+
const toSignatureType = (type, typeParametersInScope, localTypeNameRemaps = new Map()) => {
|
|
874
1568
|
if (!type)
|
|
875
1569
|
return "System.Object";
|
|
876
1570
|
switch (type.kind) {
|
|
@@ -893,20 +1587,20 @@ const toSignatureType = (type, typeParametersInScope) => {
|
|
|
893
1587
|
case "typeParameterType":
|
|
894
1588
|
return type.name;
|
|
895
1589
|
case "arrayType":
|
|
896
|
-
return `${toSignatureType(type.elementType, typeParametersInScope)}[]`;
|
|
1590
|
+
return `${toSignatureType(type.elementType, typeParametersInScope, localTypeNameRemaps)}[]`;
|
|
897
1591
|
case "tupleType":
|
|
898
1592
|
case "objectType":
|
|
899
1593
|
case "functionType":
|
|
900
1594
|
case "dictionaryType":
|
|
901
1595
|
return "System.Object";
|
|
902
1596
|
case "intersectionType":
|
|
903
|
-
return toSignatureType(type.types[0], typeParametersInScope);
|
|
1597
|
+
return toSignatureType(type.types[0], typeParametersInScope, localTypeNameRemaps);
|
|
904
1598
|
case "unionType": {
|
|
905
1599
|
const nonUndefined = type.types.filter((candidate) => {
|
|
906
1600
|
return !(candidate.kind === "primitiveType" && candidate.name === "undefined");
|
|
907
1601
|
});
|
|
908
1602
|
if (nonUndefined.length === 1 && nonUndefined[0]) {
|
|
909
|
-
const single = toSignatureType(nonUndefined[0], typeParametersInScope);
|
|
1603
|
+
const single = toSignatureType(nonUndefined[0], typeParametersInScope, localTypeNameRemaps);
|
|
910
1604
|
if (isNumericValueType(single)) {
|
|
911
1605
|
return `System.Nullable\`1[[${single}]]`;
|
|
912
1606
|
}
|
|
@@ -917,12 +1611,12 @@ const toSignatureType = (type, typeParametersInScope) => {
|
|
|
917
1611
|
case "referenceType": {
|
|
918
1612
|
if (typeParametersInScope.includes(type.name))
|
|
919
1613
|
return type.name;
|
|
920
|
-
const normalizedName = normalizeTypeReferenceName(type.name, type.typeArguments?.length);
|
|
1614
|
+
const normalizedName = normalizeTypeReferenceName(localTypeNameRemaps.get(type.name) ?? type.name, type.typeArguments?.length);
|
|
921
1615
|
if (!type.typeArguments || type.typeArguments.length === 0) {
|
|
922
1616
|
return normalizedName;
|
|
923
1617
|
}
|
|
924
1618
|
const args = type.typeArguments
|
|
925
|
-
.map((arg) => toSignatureType(arg, typeParametersInScope))
|
|
1619
|
+
.map((arg) => toSignatureType(arg, typeParametersInScope, localTypeNameRemaps))
|
|
926
1620
|
.join(",");
|
|
927
1621
|
return `${normalizedName}[[${args}]]`;
|
|
928
1622
|
}
|
|
@@ -947,13 +1641,19 @@ const makeMethodBinding = (opts) => {
|
|
|
947
1641
|
: undefined)
|
|
948
1642
|
.filter((name) => name !== undefined)));
|
|
949
1643
|
const normalizedSignature = `${opts.methodName}|(${opts.parameters
|
|
950
|
-
.map((parameter) => toSignatureType(parameter.type, typeParameterScope))
|
|
951
|
-
.join(",")}):${toSignatureType(opts.returnType, typeParameterScope)}|static=${opts.isStatic ? "true" : "false"}`;
|
|
1644
|
+
.map((parameter) => toSignatureType(parameter.type, typeParameterScope, opts.localTypeNameRemaps))
|
|
1645
|
+
.join(",")}):${toSignatureType(opts.returnType, typeParameterScope, opts.localTypeNameRemaps)}|static=${opts.isStatic ? "true" : "false"}`;
|
|
952
1646
|
const stableId = `${toStableId(opts.declaringAssemblyName, opts.declaringClrType)}::method:${opts.methodName}|${normalizedSignature}`;
|
|
953
1647
|
return {
|
|
954
1648
|
stableId,
|
|
955
1649
|
clrName: opts.methodName,
|
|
956
1650
|
normalizedSignature,
|
|
1651
|
+
semanticSignature: buildSemanticSignature({
|
|
1652
|
+
typeParameters: opts.typeParameters,
|
|
1653
|
+
parameters: opts.parameters,
|
|
1654
|
+
returnType: opts.returnType,
|
|
1655
|
+
localTypeNameRemaps: opts.localTypeNameRemaps ?? new Map(),
|
|
1656
|
+
}),
|
|
957
1657
|
arity: opts.arity,
|
|
958
1658
|
parameterCount: opts.parameters.length,
|
|
959
1659
|
isStatic: opts.isStatic,
|
|
@@ -967,16 +1667,17 @@ const makeMethodBinding = (opts) => {
|
|
|
967
1667
|
isExtensionMethod: false,
|
|
968
1668
|
};
|
|
969
1669
|
};
|
|
970
|
-
const renderClassInternal = (declaration, namespace, memberOverrides) => {
|
|
1670
|
+
const renderClassInternal = (declaration, namespace, memberOverrides, emittedName = declaration.name, localTypeNameRemaps = new Map(), brandName = declaration.name, bindingAlias = declaration.name) => {
|
|
971
1671
|
const lines = [];
|
|
1672
|
+
const isSyntheticAnonymousStructuralClass = emittedName.startsWith("__Anon_") || brandName.startsWith("__Anon_");
|
|
972
1673
|
const typeParameterScope = (declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name);
|
|
973
1674
|
const typeParameters = printTypeParameters(declaration.typeParameters);
|
|
974
|
-
const markerName = `__tsonic_type_${sanitizeForBrand(namespace)}_${sanitizeForBrand(
|
|
1675
|
+
const markerName = `__tsonic_type_${sanitizeForBrand(namespace)}_${sanitizeForBrand(brandName)}`;
|
|
975
1676
|
const heritageNames = [
|
|
976
1677
|
declaration.superClass
|
|
977
|
-
? renderPortableType(declaration.superClass, typeParameterScope)
|
|
1678
|
+
? renderPortableType(declaration.superClass, typeParameterScope, localTypeNameRemaps)
|
|
978
1679
|
: undefined,
|
|
979
|
-
...declaration.implements.map((implementedType) => renderPortableType(implementedType, typeParameterScope)),
|
|
1680
|
+
...declaration.implements.map((implementedType) => renderPortableType(implementedType, typeParameterScope, localTypeNameRemaps)),
|
|
980
1681
|
]
|
|
981
1682
|
.filter((name) => name !== undefined)
|
|
982
1683
|
.map((name) => name.trim())
|
|
@@ -987,8 +1688,11 @@ const renderClassInternal = (declaration, namespace, memberOverrides) => {
|
|
|
987
1688
|
const extendsClause = heritageNames.length > 0
|
|
988
1689
|
? ` extends ${Array.from(new Set(heritageNames)).join(", ")}`
|
|
989
1690
|
: "";
|
|
990
|
-
lines.push(`export interface ${
|
|
991
|
-
|
|
1691
|
+
lines.push(`export interface ${emittedName}$instance${typeParameters}${extendsClause} {`);
|
|
1692
|
+
if (!isSyntheticAnonymousStructuralClass) {
|
|
1693
|
+
lines.push(` readonly ${markerName}: never;`);
|
|
1694
|
+
}
|
|
1695
|
+
lines.push(renderBindingAliasMarker(namespace, bindingAlias));
|
|
992
1696
|
const instanceMembers = declaration.members.filter((member) => {
|
|
993
1697
|
if (member.kind === "constructorDeclaration")
|
|
994
1698
|
return false;
|
|
@@ -998,7 +1702,7 @@ const renderClassInternal = (declaration, namespace, memberOverrides) => {
|
|
|
998
1702
|
});
|
|
999
1703
|
for (const member of instanceMembers) {
|
|
1000
1704
|
if (member.kind === "methodDeclaration") {
|
|
1001
|
-
lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType)}`);
|
|
1705
|
+
lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType, localTypeNameRemaps)}`);
|
|
1002
1706
|
continue;
|
|
1003
1707
|
}
|
|
1004
1708
|
if (member.kind === "propertyDeclaration") {
|
|
@@ -1010,24 +1714,33 @@ const renderClassInternal = (declaration, namespace, memberOverrides) => {
|
|
|
1010
1714
|
const hasSetter = hasAccessorBody
|
|
1011
1715
|
? member.setterBody !== undefined
|
|
1012
1716
|
: !member.isReadonly;
|
|
1717
|
+
const optionalBySource = memberOverride?.emitOptionalPropertySyntax === true &&
|
|
1718
|
+
memberOverride.isOptional === true &&
|
|
1719
|
+
!member.name.startsWith("__tsonic_type_");
|
|
1720
|
+
const optionalMark = optionalBySource ? "?" : "";
|
|
1013
1721
|
const baseType = (memberOverride?.replaceWithSourceType
|
|
1014
1722
|
? memberOverride.sourceTypeText
|
|
1015
|
-
: undefined) ??
|
|
1723
|
+
: undefined) ??
|
|
1724
|
+
renderPortableType(member.type, typeParameterScope, localTypeNameRemaps);
|
|
1016
1725
|
const wrappedType = applyWrappersToBaseType(baseType, memberOverride?.wrappers ?? []);
|
|
1017
|
-
const memberType = memberOverride?.isOptional === true
|
|
1726
|
+
const memberType = memberOverride?.isOptional === true && !optionalBySource
|
|
1018
1727
|
? ensureUndefinedInType(wrappedType)
|
|
1019
1728
|
: wrappedType;
|
|
1020
1729
|
if (hasGetter && !hasSetter) {
|
|
1021
|
-
lines.push(` readonly ${member.name}: ${memberType};`);
|
|
1730
|
+
lines.push(` readonly ${member.name}${optionalMark}: ${memberType};`);
|
|
1022
1731
|
continue;
|
|
1023
1732
|
}
|
|
1024
|
-
lines.push(` ${member.name}: ${memberType};`);
|
|
1733
|
+
lines.push(` ${member.name}${optionalMark}: ${memberType};`);
|
|
1025
1734
|
}
|
|
1026
1735
|
}
|
|
1027
1736
|
lines.push("}");
|
|
1028
1737
|
lines.push("");
|
|
1029
|
-
|
|
1030
|
-
|
|
1738
|
+
if (isSyntheticAnonymousStructuralClass) {
|
|
1739
|
+
lines.push(`export type ${emittedName}${typeParameters} = ${emittedName}$instance${typeParameters};`);
|
|
1740
|
+
return lines;
|
|
1741
|
+
}
|
|
1742
|
+
lines.push(`export const ${emittedName}: {`);
|
|
1743
|
+
lines.push(` new(...args: unknown[]): ${emittedName}${typeParameters};`);
|
|
1031
1744
|
const staticMembers = declaration.members.filter((member) => {
|
|
1032
1745
|
if (member.kind === "constructorDeclaration")
|
|
1033
1746
|
return false;
|
|
@@ -1035,26 +1748,26 @@ const renderClassInternal = (declaration, namespace, memberOverrides) => {
|
|
|
1035
1748
|
});
|
|
1036
1749
|
for (const member of staticMembers) {
|
|
1037
1750
|
if (member.kind === "methodDeclaration") {
|
|
1038
|
-
lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType)}`);
|
|
1751
|
+
lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType, localTypeNameRemaps)}`);
|
|
1039
1752
|
continue;
|
|
1040
1753
|
}
|
|
1041
1754
|
if (member.kind === "propertyDeclaration") {
|
|
1042
|
-
lines.push(` ${member.name}: ${renderPortableType(member.type)};`);
|
|
1755
|
+
lines.push(` ${member.name}: ${renderPortableType(member.type, typeParameterScope, localTypeNameRemaps)};`);
|
|
1043
1756
|
}
|
|
1044
1757
|
}
|
|
1045
1758
|
lines.push("};");
|
|
1046
1759
|
lines.push("");
|
|
1047
|
-
lines.push(`export type ${
|
|
1760
|
+
lines.push(`export type ${emittedName}${typeParameters} = ${emittedName}$instance${typeParameters};`);
|
|
1048
1761
|
lines.push("");
|
|
1049
1762
|
return lines;
|
|
1050
1763
|
};
|
|
1051
|
-
const renderInterfaceInternal = (declaration, namespace, memberOverrides) => {
|
|
1764
|
+
const renderInterfaceInternal = (declaration, namespace, memberOverrides, emittedName = declaration.name, localTypeNameRemaps = new Map(), brandName = declaration.name, bindingAlias = declaration.name) => {
|
|
1052
1765
|
const lines = [];
|
|
1053
1766
|
const typeParameterScope = (declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name);
|
|
1054
1767
|
const typeParameters = printTypeParameters(declaration.typeParameters);
|
|
1055
|
-
const markerName = `__tsonic_type_${sanitizeForBrand(namespace)}_${sanitizeForBrand(
|
|
1768
|
+
const markerName = `__tsonic_type_${sanitizeForBrand(namespace)}_${sanitizeForBrand(brandName)}`;
|
|
1056
1769
|
const extendsNames = declaration.extends
|
|
1057
|
-
.map((baseType) => renderPortableType(baseType, typeParameterScope).trim())
|
|
1770
|
+
.map((baseType) => renderPortableType(baseType, typeParameterScope, localTypeNameRemaps).trim())
|
|
1058
1771
|
.filter((name) => name.length > 0 &&
|
|
1059
1772
|
name !== "unknown" &&
|
|
1060
1773
|
name !== "never" &&
|
|
@@ -1062,11 +1775,12 @@ const renderInterfaceInternal = (declaration, namespace, memberOverrides) => {
|
|
|
1062
1775
|
const extendsClause = extendsNames.length > 0
|
|
1063
1776
|
? ` extends ${Array.from(new Set(extendsNames)).join(", ")}`
|
|
1064
1777
|
: "";
|
|
1065
|
-
lines.push(`export interface ${
|
|
1778
|
+
lines.push(`export interface ${emittedName}$instance${typeParameters}${extendsClause} {`);
|
|
1066
1779
|
lines.push(` readonly ${markerName}?: never;`);
|
|
1780
|
+
lines.push(renderBindingAliasMarker(namespace, bindingAlias));
|
|
1067
1781
|
for (const member of declaration.members) {
|
|
1068
1782
|
if (member.kind === "methodSignature") {
|
|
1069
|
-
lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType)}`);
|
|
1783
|
+
lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType, localTypeNameRemaps)}`);
|
|
1070
1784
|
continue;
|
|
1071
1785
|
}
|
|
1072
1786
|
if (member.kind === "propertySignature") {
|
|
@@ -1077,7 +1791,8 @@ const renderInterfaceInternal = (declaration, namespace, memberOverrides) => {
|
|
|
1077
1791
|
const optionalMark = optionalBySource || member.isOptional ? "?" : "";
|
|
1078
1792
|
const baseType = (memberOverride?.replaceWithSourceType
|
|
1079
1793
|
? memberOverride.sourceTypeText
|
|
1080
|
-
: undefined) ??
|
|
1794
|
+
: undefined) ??
|
|
1795
|
+
renderPortableType(member.type, typeParameterScope, localTypeNameRemaps);
|
|
1081
1796
|
const wrappedType = applyWrappersToBaseType(baseType, memberOverride?.wrappers ?? []);
|
|
1082
1797
|
const memberType = memberOverride?.isOptional && !optionalBySource
|
|
1083
1798
|
? ensureUndefinedInType(wrappedType)
|
|
@@ -1087,13 +1802,13 @@ const renderInterfaceInternal = (declaration, namespace, memberOverrides) => {
|
|
|
1087
1802
|
}
|
|
1088
1803
|
lines.push("}");
|
|
1089
1804
|
lines.push("");
|
|
1090
|
-
lines.push(`export type ${
|
|
1805
|
+
lines.push(`export type ${emittedName}${typeParameters} = ${emittedName}$instance${typeParameters};`);
|
|
1091
1806
|
lines.push("");
|
|
1092
1807
|
return lines;
|
|
1093
1808
|
};
|
|
1094
|
-
const renderEnumInternal = (declaration) => {
|
|
1809
|
+
const renderEnumInternal = (declaration, emittedName = declaration.name) => {
|
|
1095
1810
|
const lines = [];
|
|
1096
|
-
lines.push(`export enum ${
|
|
1811
|
+
lines.push(`export enum ${emittedName} {`);
|
|
1097
1812
|
declaration.members.forEach((member, index) => {
|
|
1098
1813
|
lines.push(` ${member.name} = ${index},`);
|
|
1099
1814
|
});
|
|
@@ -1101,16 +1816,22 @@ const renderEnumInternal = (declaration) => {
|
|
|
1101
1816
|
lines.push("");
|
|
1102
1817
|
return lines;
|
|
1103
1818
|
};
|
|
1104
|
-
const renderStructuralAliasInternal = (declaration, namespace, memberOverrides)
|
|
1819
|
+
const renderStructuralAliasInternal = (declaration, namespace, memberOverrides, emittedName = declaration.name, localTypeNameRemaps = new Map(), brandAliasName = `${declaration.name}__Alias${(declaration.typeParameters?.length ?? 0) > 0
|
|
1820
|
+
? `_${declaration.typeParameters?.length ?? 0}`
|
|
1821
|
+
: ""}`, bindingAlias = `${declaration.name}__Alias${(declaration.typeParameters?.length ?? 0) > 0
|
|
1822
|
+
? `_${declaration.typeParameters?.length ?? 0}`
|
|
1823
|
+
: ""}`) => {
|
|
1105
1824
|
if (declaration.type.kind !== "objectType")
|
|
1106
1825
|
return [];
|
|
1107
1826
|
const lines = [];
|
|
1108
1827
|
const arity = declaration.typeParameters?.length ?? 0;
|
|
1109
1828
|
const typeParameters = printTypeParameters(declaration.typeParameters);
|
|
1110
|
-
const
|
|
1111
|
-
const
|
|
1829
|
+
const typeParameterScope = (declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name);
|
|
1830
|
+
const internalAliasName = `${emittedName}__Alias${arity > 0 ? `_${arity}` : ""}`;
|
|
1831
|
+
const markerName = `__tsonic_type_${sanitizeForBrand(namespace)}_${sanitizeForBrand(brandAliasName)}`;
|
|
1112
1832
|
lines.push(`export interface ${internalAliasName}$instance${typeParameters} {`);
|
|
1113
1833
|
lines.push(` readonly ${markerName}?: never;`);
|
|
1834
|
+
lines.push(renderBindingAliasMarker(namespace, bindingAlias));
|
|
1114
1835
|
for (const member of declaration.type.members) {
|
|
1115
1836
|
if (member.kind === "methodSignature") {
|
|
1116
1837
|
lines.push(` ${renderMethodSignature(member.name, member.typeParameters, member.parameters, member.returnType)}`);
|
|
@@ -1121,7 +1842,8 @@ const renderStructuralAliasInternal = (declaration, namespace, memberOverrides)
|
|
|
1121
1842
|
const optionalMark = member.isOptional ? "?" : "";
|
|
1122
1843
|
const baseType = (memberOverride?.replaceWithSourceType
|
|
1123
1844
|
? memberOverride.sourceTypeText
|
|
1124
|
-
: undefined) ??
|
|
1845
|
+
: undefined) ??
|
|
1846
|
+
renderPortableType(member.type, typeParameterScope, localTypeNameRemaps);
|
|
1125
1847
|
const wrappedType = applyWrappersToBaseType(baseType, memberOverride?.wrappers ?? []);
|
|
1126
1848
|
const memberType = memberOverride?.isOptional === true
|
|
1127
1849
|
? ensureUndefinedInType(wrappedType)
|
|
@@ -1135,14 +1857,67 @@ const renderStructuralAliasInternal = (declaration, namespace, memberOverrides)
|
|
|
1135
1857
|
lines.push("");
|
|
1136
1858
|
return lines;
|
|
1137
1859
|
};
|
|
1138
|
-
const
|
|
1860
|
+
const renderTypeAliasInternal = (declaration, emittedName = declaration.name, localTypeNameRemaps = new Map(), anonymousStructuralAliases = new Map()) => {
|
|
1861
|
+
if (declaration.type.kind === "objectType")
|
|
1862
|
+
return [];
|
|
1863
|
+
const typeParameterScope = (declaration.typeParameters ?? []).map((typeParameter) => typeParameter.name);
|
|
1864
|
+
const typeParameters = printTypeParameters(declaration.typeParameters);
|
|
1865
|
+
return [
|
|
1866
|
+
`export type ${emittedName}${typeParameters} = ${renderPortableType(declaration.type, typeParameterScope, localTypeNameRemaps, anonymousStructuralAliases)};`,
|
|
1867
|
+
"",
|
|
1868
|
+
];
|
|
1869
|
+
};
|
|
1870
|
+
const renderSourceAliasPlan = (plan, anonymousStructuralAliases) => {
|
|
1871
|
+
const sourceTypeParams = plan.sourceAlias?.typeParametersText ??
|
|
1872
|
+
printTypeParameters(plan.declaration.typeParameters);
|
|
1873
|
+
if (plan.declaration.type.kind === "objectType") {
|
|
1874
|
+
const arity = plan.declaration.typeParameters?.length ?? 0;
|
|
1875
|
+
const internalName = `${plan.declaration.name}__Alias${arity > 0 ? `_${arity}` : ""}`;
|
|
1876
|
+
const typeArgs = plan.sourceAlias && plan.sourceAlias.typeParameterNames.length > 0
|
|
1877
|
+
? `<${plan.sourceAlias.typeParameterNames.join(", ")}>`
|
|
1878
|
+
: plan.declaration.typeParameters &&
|
|
1879
|
+
plan.declaration.typeParameters.length > 0
|
|
1880
|
+
? `<${plan.declaration.typeParameters.map((tp) => tp.name).join(", ")}>`
|
|
1881
|
+
: "";
|
|
1882
|
+
return {
|
|
1883
|
+
line: `export type ${plan.declaration.name}${sourceTypeParams} = ${internalName}${typeArgs};`,
|
|
1884
|
+
internalImport: internalName,
|
|
1885
|
+
};
|
|
1886
|
+
}
|
|
1887
|
+
const rhs = renderPortableType(plan.declaration.type, plan.declaration.typeParameters?.map((tp) => tp.name) ?? [], new Map(), anonymousStructuralAliases);
|
|
1888
|
+
const shouldPreferSourceAliasText = plan.sourceAlias !== undefined &&
|
|
1889
|
+
!typeNodeUsesImportedTypeNames(plan.sourceAlias.type, plan.typeImportsByLocalName) &&
|
|
1890
|
+
/__\d+\b|\$instance\b/.test(rhs);
|
|
1891
|
+
return {
|
|
1892
|
+
line: `export type ${plan.declaration.name}${sourceTypeParams} = ${shouldPreferSourceAliasText
|
|
1893
|
+
? rewriteSourceTypeText(plan.sourceAlias.typeText, new Map(), anonymousStructuralAliases)
|
|
1894
|
+
: rhs};`,
|
|
1895
|
+
};
|
|
1896
|
+
};
|
|
1897
|
+
const renderContainerInternal = (entry, anonymousStructuralAliases) => {
|
|
1139
1898
|
const lines = [];
|
|
1140
1899
|
lines.push(`export abstract class ${entry.module.className}$instance {`);
|
|
1141
1900
|
for (const method of entry.methods) {
|
|
1142
|
-
|
|
1901
|
+
const sourceSignature = renderSourceFunctionSignature({
|
|
1902
|
+
declaration: method.declaration,
|
|
1903
|
+
sourceSignatures: method.sourceSignatures,
|
|
1904
|
+
localTypeNameRemaps: method.localTypeNameRemaps,
|
|
1905
|
+
anonymousStructuralAliases,
|
|
1906
|
+
});
|
|
1907
|
+
lines.push(` static ${sourceSignature
|
|
1908
|
+
? `${method.localName}${sourceSignature.typeParametersText}(${sourceSignature.parametersText}): ${sourceSignature.returnTypeText};`
|
|
1909
|
+
: renderMethodSignature(method.localName, method.declaration.typeParameters, method.declaration.parameters, method.declaration.returnType, method.localTypeNameRemaps, anonymousStructuralAliases)}`);
|
|
1143
1910
|
}
|
|
1144
1911
|
for (const variable of entry.variables) {
|
|
1145
|
-
|
|
1912
|
+
const sourceFunctionTypeText = renderSourceFunctionType({
|
|
1913
|
+
sourceSignatures: variable.sourceSignatures,
|
|
1914
|
+
localTypeNameRemaps: variable.localTypeNameRemaps,
|
|
1915
|
+
anonymousStructuralAliases,
|
|
1916
|
+
});
|
|
1917
|
+
const sourceTypeText = sourceFunctionTypeText ??
|
|
1918
|
+
renderSourceValueType(variable.sourceType, variable.localTypeNameRemaps, anonymousStructuralAliases);
|
|
1919
|
+
lines.push(` static ${variable.localName}: ${sourceTypeText ??
|
|
1920
|
+
renderPortableType(variable.declarator?.type, [], variable.localTypeNameRemaps, anonymousStructuralAliases)};`);
|
|
1146
1921
|
}
|
|
1147
1922
|
lines.push("}");
|
|
1148
1923
|
lines.push("");
|
|
@@ -1150,7 +1925,7 @@ const renderContainerInternal = (entry) => {
|
|
|
1150
1925
|
lines.push("");
|
|
1151
1926
|
return lines;
|
|
1152
1927
|
};
|
|
1153
|
-
const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
|
|
1928
|
+
const buildTypeBindingFromClass = (declaration, namespace, assemblyName, localTypeNameRemaps = new Map()) => {
|
|
1154
1929
|
const declaringClrType = toClrTypeName(namespace, declaration.name, declaration.typeParameters?.length ?? 0);
|
|
1155
1930
|
const typeStableId = toStableId(assemblyName, declaringClrType);
|
|
1156
1931
|
const typeParameterScope = declaration.typeParameters?.map((typeParameter) => typeParameter.name) ??
|
|
@@ -1162,7 +1937,7 @@ const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
|
|
|
1162
1937
|
if (member.kind === "constructorDeclaration") {
|
|
1163
1938
|
constructors.push({
|
|
1164
1939
|
normalizedSignature: `.ctor|(${member.parameters
|
|
1165
|
-
.map((parameter) => toSignatureType(parameter.type, typeParameterScope))
|
|
1940
|
+
.map((parameter) => toSignatureType(parameter.type, typeParameterScope, localTypeNameRemaps))
|
|
1166
1941
|
.join(",")})|static=false`,
|
|
1167
1942
|
isStatic: false,
|
|
1168
1943
|
parameterCount: member.parameters.length,
|
|
@@ -1176,12 +1951,14 @@ const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
|
|
|
1176
1951
|
methodName: member.name,
|
|
1177
1952
|
parameters: member.parameters,
|
|
1178
1953
|
returnType: member.returnType,
|
|
1954
|
+
typeParameters: member.typeParameters,
|
|
1179
1955
|
arity: member.typeParameters?.length ?? 0,
|
|
1180
1956
|
parameterModifiers: buildParameterModifiers(member.parameters),
|
|
1181
1957
|
isStatic: member.isStatic,
|
|
1182
1958
|
isAbstract: member.body === undefined,
|
|
1183
1959
|
isVirtual: member.isVirtual,
|
|
1184
1960
|
isOverride: member.isOverride,
|
|
1961
|
+
localTypeNameRemaps,
|
|
1185
1962
|
}));
|
|
1186
1963
|
continue;
|
|
1187
1964
|
}
|
|
@@ -1193,11 +1970,12 @@ const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
|
|
|
1193
1970
|
const hasSetter = hasAccessorBody
|
|
1194
1971
|
? member.setterBody !== undefined
|
|
1195
1972
|
: !member.isReadonly;
|
|
1196
|
-
const propertyType = toSignatureType(member.type, typeParameterScope);
|
|
1973
|
+
const propertyType = toSignatureType(member.type, typeParameterScope, localTypeNameRemaps);
|
|
1197
1974
|
properties.push({
|
|
1198
1975
|
stableId: `${typeStableId}::property:${member.name}`,
|
|
1199
1976
|
clrName: member.name,
|
|
1200
1977
|
normalizedSignature: `${member.name}|:${propertyType}|static=${member.isStatic ? "true" : "false"}|accessor=${hasGetter && hasSetter ? "getset" : hasSetter ? "set" : "get"}`,
|
|
1978
|
+
semanticType: rewriteBindingSemanticType(member.type, localTypeNameRemaps),
|
|
1201
1979
|
isStatic: member.isStatic,
|
|
1202
1980
|
isAbstract: member.getterBody === undefined && member.setterBody === undefined
|
|
1203
1981
|
? false
|
|
@@ -1215,6 +1993,7 @@ const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
|
|
|
1215
1993
|
return {
|
|
1216
1994
|
stableId: typeStableId,
|
|
1217
1995
|
clrName: declaringClrType,
|
|
1996
|
+
alias: toBindingTypeAlias(namespace, declaration.name, declaration.typeParameters?.length ?? 0),
|
|
1218
1997
|
assemblyName,
|
|
1219
1998
|
kind: declaration.isStruct ? "Struct" : "Class",
|
|
1220
1999
|
accessibility: "Public",
|
|
@@ -1239,7 +2018,7 @@ const buildTypeBindingFromClass = (declaration, namespace, assemblyName) => {
|
|
|
1239
2018
|
],
|
|
1240
2019
|
};
|
|
1241
2020
|
};
|
|
1242
|
-
const buildTypeBindingFromInterface = (declaration, namespace, assemblyName) => {
|
|
2021
|
+
const buildTypeBindingFromInterface = (declaration, namespace, assemblyName, localTypeNameRemaps = new Map()) => {
|
|
1243
2022
|
const declaringClrType = toClrTypeName(namespace, declaration.name, declaration.typeParameters?.length ?? 0);
|
|
1244
2023
|
const typeStableId = toStableId(assemblyName, declaringClrType);
|
|
1245
2024
|
const typeParameterScope = declaration.typeParameters?.map((typeParameter) => typeParameter.name) ??
|
|
@@ -1254,17 +2033,21 @@ const buildTypeBindingFromInterface = (declaration, namespace, assemblyName) =>
|
|
|
1254
2033
|
methodName: member.name,
|
|
1255
2034
|
parameters: member.parameters,
|
|
1256
2035
|
returnType: member.returnType,
|
|
2036
|
+
typeParameters: member.typeParameters,
|
|
1257
2037
|
arity: member.typeParameters?.length ?? 0,
|
|
1258
2038
|
parameterModifiers: buildParameterModifiers(member.parameters),
|
|
1259
2039
|
isStatic: false,
|
|
1260
2040
|
isAbstract: true,
|
|
2041
|
+
localTypeNameRemaps,
|
|
1261
2042
|
}));
|
|
1262
2043
|
continue;
|
|
1263
2044
|
}
|
|
1264
2045
|
properties.push({
|
|
1265
2046
|
stableId: `${typeStableId}::property:${member.name}`,
|
|
1266
2047
|
clrName: member.name,
|
|
1267
|
-
normalizedSignature: `${member.name}|:${toSignatureType(member.type, typeParameterScope)}|static=false|accessor=${member.isReadonly ? "get" : "getset"}`,
|
|
2048
|
+
normalizedSignature: `${member.name}|:${toSignatureType(member.type, typeParameterScope, localTypeNameRemaps)}|static=false|accessor=${member.isReadonly ? "get" : "getset"}`,
|
|
2049
|
+
semanticType: rewriteBindingSemanticType(member.type, localTypeNameRemaps),
|
|
2050
|
+
semanticOptional: member.isOptional,
|
|
1268
2051
|
isStatic: false,
|
|
1269
2052
|
isAbstract: true,
|
|
1270
2053
|
isVirtual: false,
|
|
@@ -1279,6 +2062,7 @@ const buildTypeBindingFromInterface = (declaration, namespace, assemblyName) =>
|
|
|
1279
2062
|
return {
|
|
1280
2063
|
stableId: typeStableId,
|
|
1281
2064
|
clrName: declaringClrType,
|
|
2065
|
+
alias: toBindingTypeAlias(namespace, declaration.name, declaration.typeParameters?.length ?? 0),
|
|
1282
2066
|
assemblyName,
|
|
1283
2067
|
kind: declaration.isStruct ? "Struct" : "Interface",
|
|
1284
2068
|
accessibility: "Public",
|
|
@@ -1311,6 +2095,7 @@ const buildTypeBindingFromEnum = (declaration, namespace, assemblyName) => {
|
|
|
1311
2095
|
return {
|
|
1312
2096
|
stableId: typeStableId,
|
|
1313
2097
|
clrName: declaringClrType,
|
|
2098
|
+
alias: toBindingTypeAlias(namespace, declaration.name),
|
|
1314
2099
|
assemblyName,
|
|
1315
2100
|
kind: "Enum",
|
|
1316
2101
|
accessibility: "Public",
|
|
@@ -1326,7 +2111,7 @@ const buildTypeBindingFromEnum = (declaration, namespace, assemblyName) => {
|
|
|
1326
2111
|
constructors: [],
|
|
1327
2112
|
};
|
|
1328
2113
|
};
|
|
1329
|
-
const buildTypeBindingFromStructuralAlias = (declaration, namespace, assemblyName) => {
|
|
2114
|
+
const buildTypeBindingFromStructuralAlias = (declaration, namespace, assemblyName, localTypeNameRemaps = new Map()) => {
|
|
1330
2115
|
if (declaration.type.kind !== "objectType")
|
|
1331
2116
|
return undefined;
|
|
1332
2117
|
const arity = declaration.typeParameters?.length ?? 0;
|
|
@@ -1345,17 +2130,21 @@ const buildTypeBindingFromStructuralAlias = (declaration, namespace, assemblyNam
|
|
|
1345
2130
|
methodName: member.name,
|
|
1346
2131
|
parameters: member.parameters,
|
|
1347
2132
|
returnType: member.returnType,
|
|
2133
|
+
typeParameters: member.typeParameters,
|
|
1348
2134
|
arity: member.typeParameters?.length ?? 0,
|
|
1349
2135
|
parameterModifiers: buildParameterModifiers(member.parameters),
|
|
1350
2136
|
isStatic: false,
|
|
1351
2137
|
isAbstract: true,
|
|
2138
|
+
localTypeNameRemaps,
|
|
1352
2139
|
}));
|
|
1353
2140
|
continue;
|
|
1354
2141
|
}
|
|
1355
2142
|
properties.push({
|
|
1356
2143
|
stableId: `${typeStableId}::property:${member.name}`,
|
|
1357
2144
|
clrName: member.name,
|
|
1358
|
-
normalizedSignature: `${member.name}|:${toSignatureType(member.type, typeParameterScope)}|static=false|accessor=${member.isReadonly ? "get" : "getset"}`,
|
|
2145
|
+
normalizedSignature: `${member.name}|:${toSignatureType(member.type, typeParameterScope, localTypeNameRemaps)}|static=false|accessor=${member.isReadonly ? "get" : "getset"}`,
|
|
2146
|
+
semanticType: rewriteBindingSemanticType(member.type, localTypeNameRemaps),
|
|
2147
|
+
semanticOptional: member.isOptional,
|
|
1359
2148
|
isStatic: false,
|
|
1360
2149
|
isAbstract: true,
|
|
1361
2150
|
isVirtual: false,
|
|
@@ -1370,6 +2159,7 @@ const buildTypeBindingFromStructuralAlias = (declaration, namespace, assemblyNam
|
|
|
1370
2159
|
return {
|
|
1371
2160
|
stableId: typeStableId,
|
|
1372
2161
|
clrName: declaringClrType,
|
|
2162
|
+
alias: toBindingTypeAlias(namespace, internalAliasName, arity),
|
|
1373
2163
|
assemblyName,
|
|
1374
2164
|
kind: declaration.isStruct ? "Struct" : "Class",
|
|
1375
2165
|
accessibility: "Public",
|
|
@@ -1398,11 +2188,13 @@ const buildTypeBindingFromContainer = (entry, namespace, assemblyName) => {
|
|
|
1398
2188
|
arity: method.declaration.typeParameters?.length ?? 0,
|
|
1399
2189
|
parameterModifiers: buildParameterModifiers(method.declaration.parameters),
|
|
1400
2190
|
isStatic: true,
|
|
2191
|
+
localTypeNameRemaps: method.localTypeNameRemaps,
|
|
1401
2192
|
}));
|
|
1402
2193
|
const properties = entry.variables.map((variable) => ({
|
|
1403
2194
|
stableId: `${typeStableId}::property:${variable.localName}`,
|
|
1404
2195
|
clrName: variable.localName,
|
|
1405
|
-
normalizedSignature: `${variable.localName}|:${toSignatureType(variable.declarator?.type, [])}|static=true|accessor=getset`,
|
|
2196
|
+
normalizedSignature: `${variable.localName}|:${toSignatureType(variable.declarator?.type, [], variable.localTypeNameRemaps)}|static=true|accessor=getset`,
|
|
2197
|
+
semanticType: rewriteBindingSemanticType(variable.declarator?.type, variable.localTypeNameRemaps),
|
|
1406
2198
|
isStatic: true,
|
|
1407
2199
|
isAbstract: false,
|
|
1408
2200
|
isVirtual: false,
|
|
@@ -1416,6 +2208,7 @@ const buildTypeBindingFromContainer = (entry, namespace, assemblyName) => {
|
|
|
1416
2208
|
return {
|
|
1417
2209
|
stableId: typeStableId,
|
|
1418
2210
|
clrName: declaringClrType,
|
|
2211
|
+
alias: toBindingTypeAlias(namespace, entry.module.className),
|
|
1419
2212
|
assemblyName,
|
|
1420
2213
|
kind: "Class",
|
|
1421
2214
|
accessibility: "Public",
|
|
@@ -1451,37 +2244,105 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1451
2244
|
for (const [namespace, moduleList] of Array.from(modulesByNamespace.entries())) {
|
|
1452
2245
|
const typeDeclarations = [];
|
|
1453
2246
|
const moduleContainers = [];
|
|
2247
|
+
const crossNamespaceReexportsGrouped = new Map();
|
|
2248
|
+
const crossNamespaceTypeDeclarations = [];
|
|
2249
|
+
const seenCrossNamespaceTypeDeclarationKeys = new Set();
|
|
1454
2250
|
const valueExportsMap = new Map();
|
|
1455
2251
|
const seenTypeDeclarationKeys = new Set();
|
|
1456
|
-
const
|
|
1457
|
-
const sourceAliasInternalImports = new Set();
|
|
2252
|
+
const sourceAliasPlans = [];
|
|
1458
2253
|
const memberOverrides = [];
|
|
2254
|
+
const internalTypeImportByAlias = new Map();
|
|
2255
|
+
const facadeTypeImportByAlias = new Map();
|
|
1459
2256
|
const wrapperImportByAlias = new Map();
|
|
2257
|
+
const internalHelperTypeDeclarationsByKey = new Map();
|
|
2258
|
+
const internalHelperTypeRemapsByModuleKey = new Map();
|
|
2259
|
+
const getInternalHelperTypeName = (moduleFileKey, localName) => {
|
|
2260
|
+
return `__Local_${sanitizeForBrand(moduleFileKey)}_${sanitizeForBrand(localName)}`;
|
|
2261
|
+
};
|
|
2262
|
+
const registerInternalHelperTypeClosure = (opts) => {
|
|
2263
|
+
if (!opts.sourceIndex)
|
|
2264
|
+
return { ok: true, value: new Map() };
|
|
2265
|
+
const moduleFileKey = normalizeModuleFileKey(opts.declarationModule.filePath);
|
|
2266
|
+
const remaps = internalHelperTypeRemapsByModuleKey.get(moduleFileKey) ?? new Map();
|
|
2267
|
+
if (!internalHelperTypeRemapsByModuleKey.has(moduleFileKey)) {
|
|
2268
|
+
internalHelperTypeRemapsByModuleKey.set(moduleFileKey, remaps);
|
|
2269
|
+
}
|
|
2270
|
+
const visiting = new Set();
|
|
2271
|
+
const visitLocalType = (localName) => {
|
|
2272
|
+
if (opts.sourceIndex?.exportedTypeDeclarationNames.has(localName)) {
|
|
2273
|
+
return { ok: true, value: undefined };
|
|
2274
|
+
}
|
|
2275
|
+
const declaration = resolveModuleLocalDeclaration(opts.declarationModule, localName);
|
|
2276
|
+
if (!declaration)
|
|
2277
|
+
return { ok: true, value: undefined };
|
|
2278
|
+
const kind = classifyLocalTypeDeclarationKind(declaration);
|
|
2279
|
+
if (!kind)
|
|
2280
|
+
return { ok: true, value: undefined };
|
|
2281
|
+
const localTypeDeclaration = declaration;
|
|
2282
|
+
const key = `${moduleFileKey}::${localName}`;
|
|
2283
|
+
if (!remaps.has(localName)) {
|
|
2284
|
+
remaps.set(localName, getInternalHelperTypeName(moduleFileKey, localName));
|
|
2285
|
+
}
|
|
2286
|
+
if (internalHelperTypeDeclarationsByKey.has(key)) {
|
|
2287
|
+
return { ok: true, value: undefined };
|
|
2288
|
+
}
|
|
2289
|
+
if (visiting.has(key))
|
|
2290
|
+
return { ok: true, value: undefined };
|
|
2291
|
+
visiting.add(key);
|
|
2292
|
+
const nestedReferencedNames = new Set();
|
|
2293
|
+
collectReferencedPortableTypeNamesFromDeclaration(localTypeDeclaration, nestedReferencedNames);
|
|
2294
|
+
for (const nestedName of nestedReferencedNames) {
|
|
2295
|
+
const visited = visitLocalType(nestedName);
|
|
2296
|
+
if (!visited.ok)
|
|
2297
|
+
return visited;
|
|
2298
|
+
}
|
|
2299
|
+
visiting.delete(key);
|
|
2300
|
+
internalHelperTypeDeclarationsByKey.set(key, {
|
|
2301
|
+
key,
|
|
2302
|
+
moduleFileKey,
|
|
2303
|
+
declaringNamespace: opts.declarationModule.namespace,
|
|
2304
|
+
emittedName: remaps.get(localName),
|
|
2305
|
+
originalName: localName,
|
|
2306
|
+
kind,
|
|
2307
|
+
declaration: localTypeDeclaration,
|
|
2308
|
+
});
|
|
2309
|
+
return { ok: true, value: undefined };
|
|
2310
|
+
};
|
|
2311
|
+
for (const referencedName of opts.referencedNames) {
|
|
2312
|
+
const visited = visitLocalType(referencedName);
|
|
2313
|
+
if (!visited.ok)
|
|
2314
|
+
return visited;
|
|
2315
|
+
}
|
|
2316
|
+
return { ok: true, value: new Map(remaps) };
|
|
2317
|
+
};
|
|
1460
2318
|
const registerValueExport = (valueExport) => {
|
|
1461
2319
|
const existing = valueExportsMap.get(valueExport.exportName);
|
|
1462
2320
|
if (!existing) {
|
|
1463
2321
|
valueExportsMap.set(valueExport.exportName, valueExport);
|
|
1464
2322
|
return { ok: true, value: undefined };
|
|
1465
2323
|
}
|
|
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;
|
|
2324
|
+
const sameBinding = areBindingSemanticsEqual(existing.binding, valueExport.binding);
|
|
1472
2325
|
const normalizeFunctionFacade = (facade) => {
|
|
1473
2326
|
const declaration = facade.declaration;
|
|
1474
2327
|
const typeParametersText = printTypeParameters(declaration.typeParameters);
|
|
1475
2328
|
const typeParameterNames = declaration.typeParameters?.map((typeParameter) => typeParameter.name) ?? [];
|
|
1476
|
-
const parametersText = renderUnknownParameters(declaration.parameters, typeParameterNames);
|
|
1477
|
-
const returnTypeText = renderPortableType(declaration.returnType, typeParameterNames);
|
|
2329
|
+
const parametersText = renderUnknownParameters(declaration.parameters, typeParameterNames, facade.localTypeNameRemaps);
|
|
2330
|
+
const returnTypeText = renderPortableType(declaration.returnType, typeParameterNames, facade.localTypeNameRemaps);
|
|
1478
2331
|
const sourceSignatures = (facade.sourceSignatures ?? [])
|
|
1479
|
-
.map((signature) => `${signature.typeParametersText}(${signature.
|
|
2332
|
+
.map((signature) => `${signature.typeParametersText}(${signature.parameters
|
|
2333
|
+
.map((parameter) => `${parameter.prefixText}${parameter.typeText}`)
|
|
2334
|
+
.join(", ")}):${signature.returnTypeText}`)
|
|
1480
2335
|
.sort((left, right) => left.localeCompare(right))
|
|
1481
2336
|
.join("||");
|
|
1482
2337
|
return `${typeParametersText}(${parametersText}):${returnTypeText}|source=${sourceSignatures}`;
|
|
1483
2338
|
};
|
|
1484
|
-
const normalizeVariableFacade = (declarator) =>
|
|
2339
|
+
const normalizeVariableFacade = (declarator, localTypeNameRemaps) => {
|
|
2340
|
+
const functionType = resolveFunctionTypeFromValueDeclarator(declarator);
|
|
2341
|
+
if (functionType) {
|
|
2342
|
+
return JSON.stringify(buildSemanticSignatureFromFunctionType(functionType, localTypeNameRemaps));
|
|
2343
|
+
}
|
|
2344
|
+
return renderPortableType(declarator?.type, [], localTypeNameRemaps);
|
|
2345
|
+
};
|
|
1485
2346
|
const sameFacade = (() => {
|
|
1486
2347
|
if (existing.facade.kind !== valueExport.facade.kind)
|
|
1487
2348
|
return false;
|
|
@@ -1492,8 +2353,8 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1492
2353
|
}
|
|
1493
2354
|
if (existing.facade.kind === "variable" &&
|
|
1494
2355
|
valueExport.facade.kind === "variable") {
|
|
1495
|
-
return (normalizeVariableFacade(existing.facade.declarator) ===
|
|
1496
|
-
normalizeVariableFacade(valueExport.facade.declarator));
|
|
2356
|
+
return (normalizeVariableFacade(existing.facade.declarator, existing.facade.localTypeNameRemaps) ===
|
|
2357
|
+
normalizeVariableFacade(valueExport.facade.declarator, valueExport.facade.localTypeNameRemaps));
|
|
1497
2358
|
}
|
|
1498
2359
|
return false;
|
|
1499
2360
|
})();
|
|
@@ -1526,32 +2387,113 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1526
2387
|
}
|
|
1527
2388
|
return { ok: true, value: undefined };
|
|
1528
2389
|
};
|
|
2390
|
+
const registerCrossNamespaceReexport = (opts) => {
|
|
2391
|
+
if (opts.declaringNamespace === namespace)
|
|
2392
|
+
return;
|
|
2393
|
+
const moduleSpecifier = `./${moduleNamespacePath(opts.declaringNamespace)}.js`;
|
|
2394
|
+
const key = `${moduleSpecifier}|${opts.kind}`;
|
|
2395
|
+
const specifier = opts.exportName === opts.localName
|
|
2396
|
+
? opts.exportName
|
|
2397
|
+
: `${opts.localName} as ${opts.exportName}`;
|
|
2398
|
+
const existing = crossNamespaceReexportsGrouped.get(key) ?? [];
|
|
2399
|
+
existing.push(specifier);
|
|
2400
|
+
crossNamespaceReexportsGrouped.set(key, existing);
|
|
2401
|
+
};
|
|
2402
|
+
const registerCrossNamespaceTypeDeclaration = (symbol) => {
|
|
2403
|
+
if (symbol.declaringNamespace === namespace)
|
|
2404
|
+
return;
|
|
2405
|
+
const key = `${symbol.declaringNamespace}|${symbol.declaringClassName}|${symbol.localName}|${symbol.kind}`;
|
|
2406
|
+
if (seenCrossNamespaceTypeDeclarationKeys.has(key))
|
|
2407
|
+
return;
|
|
2408
|
+
seenCrossNamespaceTypeDeclarationKeys.add(key);
|
|
2409
|
+
crossNamespaceTypeDeclarations.push(symbol);
|
|
2410
|
+
};
|
|
2411
|
+
const registerSourceTypeImportCandidates = (sourceIndex, moduleKey, moduleFilePath) => {
|
|
2412
|
+
for (const [localName, imported] of sourceIndex.typeImportsByLocalName) {
|
|
2413
|
+
if (sourceIndex.wrapperImportsByLocalName.has(localName))
|
|
2414
|
+
continue;
|
|
2415
|
+
const internalImport = resolveSourceTypeImportBinding({
|
|
2416
|
+
context: "internal",
|
|
2417
|
+
currentNamespace: namespace,
|
|
2418
|
+
currentModuleKey: moduleKey,
|
|
2419
|
+
localName,
|
|
2420
|
+
imported,
|
|
2421
|
+
modulesByFileKey,
|
|
2422
|
+
});
|
|
2423
|
+
if (!internalImport.ok)
|
|
2424
|
+
return internalImport;
|
|
2425
|
+
if (internalImport.value) {
|
|
2426
|
+
const registered = registerSourceTypeImportBinding(internalTypeImportByAlias, internalImport.value, namespace, moduleFilePath);
|
|
2427
|
+
if (!registered.ok)
|
|
2428
|
+
return registered;
|
|
2429
|
+
}
|
|
2430
|
+
const facadeImport = resolveSourceTypeImportBinding({
|
|
2431
|
+
context: "facade",
|
|
2432
|
+
currentNamespace: namespace,
|
|
2433
|
+
currentModuleKey: moduleKey,
|
|
2434
|
+
localName,
|
|
2435
|
+
imported,
|
|
2436
|
+
modulesByFileKey,
|
|
2437
|
+
});
|
|
2438
|
+
if (!facadeImport.ok)
|
|
2439
|
+
return facadeImport;
|
|
2440
|
+
if (facadeImport.value) {
|
|
2441
|
+
const registered = registerSourceTypeImportBinding(facadeTypeImportByAlias, facadeImport.value, namespace, moduleFilePath);
|
|
2442
|
+
if (!registered.ok)
|
|
2443
|
+
return registered;
|
|
2444
|
+
}
|
|
2445
|
+
}
|
|
2446
|
+
return { ok: true, value: undefined };
|
|
2447
|
+
};
|
|
2448
|
+
const registerFacadeLocalTypeReferenceImports = (opts) => {
|
|
2449
|
+
const typeParameterNames = new Set((opts.typeParameters ?? []).map((typeParameter) => typeParameter.name));
|
|
2450
|
+
const referencedNames = new Set();
|
|
2451
|
+
for (const parameterType of opts.parameterTypes) {
|
|
2452
|
+
collectReferencedPortableTypeNames(parameterType, typeParameterNames, referencedNames);
|
|
2453
|
+
}
|
|
2454
|
+
collectReferencedPortableTypeNames(opts.returnType, typeParameterNames, referencedNames);
|
|
2455
|
+
const helperTypeRemaps = registerInternalHelperTypeClosure({
|
|
2456
|
+
declarationModule: opts.declarationModule,
|
|
2457
|
+
sourceIndex: opts.sourceIndex,
|
|
2458
|
+
referencedNames,
|
|
2459
|
+
});
|
|
2460
|
+
if (!helperTypeRemaps.ok)
|
|
2461
|
+
return helperTypeRemaps;
|
|
2462
|
+
if (!opts.sourceIndex)
|
|
2463
|
+
return helperTypeRemaps;
|
|
2464
|
+
if (opts.declarationNamespace === namespace) {
|
|
2465
|
+
return helperTypeRemaps;
|
|
2466
|
+
}
|
|
2467
|
+
const moduleSpecifier = `./${moduleNamespacePath(opts.declarationNamespace)}.js`;
|
|
2468
|
+
for (const referencedName of referencedNames) {
|
|
2469
|
+
if (!opts.sourceIndex.exportedTypeDeclarationNames.has(referencedName)) {
|
|
2470
|
+
continue;
|
|
2471
|
+
}
|
|
2472
|
+
const registered = registerSourceTypeImportBinding(facadeTypeImportByAlias, {
|
|
2473
|
+
importedName: referencedName,
|
|
2474
|
+
localName: referencedName,
|
|
2475
|
+
source: moduleSpecifier,
|
|
2476
|
+
}, namespace, opts.declarationFilePath);
|
|
2477
|
+
if (!registered.ok)
|
|
2478
|
+
return registered;
|
|
2479
|
+
}
|
|
2480
|
+
return helperTypeRemaps;
|
|
2481
|
+
};
|
|
1529
2482
|
for (const module of moduleList.sort((left, right) => left.filePath.localeCompare(right.filePath))) {
|
|
1530
2483
|
const moduleKey = normalizeModuleFileKey(module.filePath);
|
|
1531
2484
|
const sourceIndex = sourceIndexByFileKey.get(moduleKey);
|
|
1532
2485
|
if (sourceIndex) {
|
|
2486
|
+
const registered = registerSourceTypeImportCandidates(sourceIndex, moduleKey, module.filePath);
|
|
2487
|
+
if (!registered.ok)
|
|
2488
|
+
return registered;
|
|
1533
2489
|
const exportedAliasDecls = module.body.filter((stmt) => stmt.kind === "typeAliasDeclaration" && stmt.isExported);
|
|
1534
2490
|
for (const alias of exportedAliasDecls) {
|
|
1535
2491
|
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};`);
|
|
2492
|
+
sourceAliasPlans.push({
|
|
2493
|
+
declaration: alias,
|
|
2494
|
+
sourceAlias,
|
|
2495
|
+
typeImportsByLocalName: sourceIndex.typeImportsByLocalName,
|
|
2496
|
+
});
|
|
1555
2497
|
}
|
|
1556
2498
|
const exportedClasses = module.body.filter((stmt) => stmt.kind === "classDeclaration" && stmt.isExported);
|
|
1557
2499
|
const exportedInterfaces = module.body.filter((stmt) => stmt.kind === "interfaceDeclaration" && stmt.isExported);
|
|
@@ -1692,6 +2634,16 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1692
2634
|
const exportKind = classifyDeclarationKind(declaration, declarationModule.filePath, exportItem.name);
|
|
1693
2635
|
if (!exportKind.ok)
|
|
1694
2636
|
return exportKind;
|
|
2637
|
+
if (declarationModule.namespace !== namespace) {
|
|
2638
|
+
registerCrossNamespaceReexport({
|
|
2639
|
+
declaringNamespace: declarationModule.namespace,
|
|
2640
|
+
exportName: exportItem.name,
|
|
2641
|
+
localName: resolved.value.clrName,
|
|
2642
|
+
kind: exportKind.value === "interface" || exportKind.value === "typeAlias"
|
|
2643
|
+
? "type"
|
|
2644
|
+
: "value",
|
|
2645
|
+
});
|
|
2646
|
+
}
|
|
1695
2647
|
if (exportKind.value === "function") {
|
|
1696
2648
|
const functionDeclaration = declaration.kind === "functionDeclaration"
|
|
1697
2649
|
? declaration
|
|
@@ -1702,6 +2654,24 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1702
2654
|
error: `Invalid function export '${exportItem.name}' in ${declarationModule.filePath}: expected function declaration.`,
|
|
1703
2655
|
};
|
|
1704
2656
|
}
|
|
2657
|
+
const declarationModuleKey = normalizeModuleFileKey(declarationModule.filePath);
|
|
2658
|
+
const declarationSourceIndex = sourceIndexByFileKey.get(declarationModuleKey);
|
|
2659
|
+
if (declarationSourceIndex) {
|
|
2660
|
+
const registered = registerSourceTypeImportCandidates(declarationSourceIndex, declarationModuleKey, declarationModule.filePath);
|
|
2661
|
+
if (!registered.ok)
|
|
2662
|
+
return registered;
|
|
2663
|
+
}
|
|
2664
|
+
const registeredLocalTypeRefs = registerFacadeLocalTypeReferenceImports({
|
|
2665
|
+
declarationModule,
|
|
2666
|
+
declarationNamespace: declarationModule.namespace,
|
|
2667
|
+
declarationFilePath: declarationModule.filePath,
|
|
2668
|
+
sourceIndex: declarationSourceIndex,
|
|
2669
|
+
typeParameters: functionDeclaration.typeParameters,
|
|
2670
|
+
parameterTypes: functionDeclaration.parameters.map((parameter) => parameter.type),
|
|
2671
|
+
returnType: functionDeclaration.returnType,
|
|
2672
|
+
});
|
|
2673
|
+
if (!registeredLocalTypeRefs.ok)
|
|
2674
|
+
return registeredLocalTypeRefs;
|
|
1705
2675
|
const registered = registerValueExport({
|
|
1706
2676
|
exportName: exportItem.name,
|
|
1707
2677
|
binding: {
|
|
@@ -1713,6 +2683,7 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1713
2683
|
facade: {
|
|
1714
2684
|
kind: "function",
|
|
1715
2685
|
declaration: functionDeclaration,
|
|
2686
|
+
localTypeNameRemaps: registeredLocalTypeRefs.value,
|
|
1716
2687
|
sourceSignatures: sourceIndexByFileKey
|
|
1717
2688
|
.get(normalizeModuleFileKey(declarationModule.filePath))
|
|
1718
2689
|
?.exportedFunctionSignaturesByName.get(resolved.value.clrName) ?? [],
|
|
@@ -1732,23 +2703,63 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1732
2703
|
error: `Invalid variable export '${exportItem.name}' in ${declarationModule.filePath}: expected variable declaration.`,
|
|
1733
2704
|
};
|
|
1734
2705
|
}
|
|
2706
|
+
const declarationModuleKey = normalizeModuleFileKey(declarationModule.filePath);
|
|
2707
|
+
const declarationSourceIndex = sourceIndexByFileKey.get(declarationModuleKey);
|
|
2708
|
+
if (declarationSourceIndex) {
|
|
2709
|
+
const registered = registerSourceTypeImportCandidates(declarationSourceIndex, declarationModuleKey, declarationModule.filePath);
|
|
2710
|
+
if (!registered.ok)
|
|
2711
|
+
return registered;
|
|
2712
|
+
}
|
|
1735
2713
|
const declarator = declarationStatement.declarations.find((candidate) => candidate.name.kind === "identifierPattern" &&
|
|
1736
2714
|
candidate.name.name === resolved.value.clrName);
|
|
2715
|
+
const exportedFunctionType = resolveFunctionTypeFromValueDeclarator(declarator && declarator.name.kind === "identifierPattern"
|
|
2716
|
+
? {
|
|
2717
|
+
kind: declarator.kind,
|
|
2718
|
+
name: declarator.name,
|
|
2719
|
+
type: declarator.type,
|
|
2720
|
+
initializer: declarator.initializer,
|
|
2721
|
+
}
|
|
2722
|
+
: undefined);
|
|
2723
|
+
const registeredLocalTypeRefs = registerFacadeLocalTypeReferenceImports({
|
|
2724
|
+
declarationModule,
|
|
2725
|
+
declarationNamespace: declarationModule.namespace,
|
|
2726
|
+
declarationFilePath: declarationModule.filePath,
|
|
2727
|
+
sourceIndex: declarationSourceIndex,
|
|
2728
|
+
typeParameters: undefined,
|
|
2729
|
+
parameterTypes: exportedFunctionType
|
|
2730
|
+
? [exportedFunctionType]
|
|
2731
|
+
: declarator?.type
|
|
2732
|
+
? [declarator.type]
|
|
2733
|
+
: [],
|
|
2734
|
+
returnType: undefined,
|
|
2735
|
+
});
|
|
2736
|
+
if (!registeredLocalTypeRefs.ok)
|
|
2737
|
+
return registeredLocalTypeRefs;
|
|
1737
2738
|
const registered = registerValueExport({
|
|
1738
2739
|
exportName: exportItem.name,
|
|
1739
2740
|
binding: {
|
|
1740
|
-
kind: "field",
|
|
2741
|
+
kind: exportedFunctionType ? "functionType" : "field",
|
|
1741
2742
|
clrName: resolved.value.clrName,
|
|
1742
2743
|
declaringClrType: toClrTypeName(declarationModule.namespace, declarationModule.className),
|
|
1743
2744
|
declaringAssemblyName: assemblyName,
|
|
2745
|
+
semanticType: exportedFunctionType
|
|
2746
|
+
? undefined
|
|
2747
|
+
: rewriteBindingSemanticType(declarator?.type, registeredLocalTypeRefs.value),
|
|
2748
|
+
semanticSignature: exportedFunctionType
|
|
2749
|
+
? buildSemanticSignatureFromFunctionType(exportedFunctionType, registeredLocalTypeRefs.value)
|
|
2750
|
+
: undefined,
|
|
1744
2751
|
},
|
|
1745
2752
|
facade: {
|
|
1746
2753
|
kind: "variable",
|
|
2754
|
+
localTypeNameRemaps: registeredLocalTypeRefs.value,
|
|
2755
|
+
sourceType: declarationSourceIndex?.exportedValueTypesByName.get(resolved.value.clrName),
|
|
2756
|
+
sourceSignatures: declarationSourceIndex?.exportedFunctionSignaturesByName.get(resolved.value.clrName) ?? [],
|
|
1747
2757
|
declarator: declarator && declarator.name.kind === "identifierPattern"
|
|
1748
2758
|
? {
|
|
1749
2759
|
kind: declarator.kind,
|
|
1750
2760
|
name: declarator.name,
|
|
1751
2761
|
type: declarator.type,
|
|
2762
|
+
initializer: declarator.initializer,
|
|
1752
2763
|
}
|
|
1753
2764
|
: undefined,
|
|
1754
2765
|
},
|
|
@@ -1761,6 +2772,25 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1761
2772
|
exportKind.value === "interface" ||
|
|
1762
2773
|
exportKind.value === "enum" ||
|
|
1763
2774
|
exportKind.value === "typeAlias") {
|
|
2775
|
+
if (declarationModule.namespace !== namespace) {
|
|
2776
|
+
registerCrossNamespaceTypeDeclaration({
|
|
2777
|
+
exportName: exportItem.name,
|
|
2778
|
+
localName: resolved.value.clrName,
|
|
2779
|
+
kind: exportKind.value,
|
|
2780
|
+
declaration,
|
|
2781
|
+
declaringNamespace: declarationModule.namespace,
|
|
2782
|
+
declaringClassName: declarationModule.className,
|
|
2783
|
+
declaringFilePath: declarationModule.filePath,
|
|
2784
|
+
});
|
|
2785
|
+
continue;
|
|
2786
|
+
}
|
|
2787
|
+
const declarationModuleKey = normalizeModuleFileKey(declarationModule.filePath);
|
|
2788
|
+
const declarationSourceIndex = sourceIndexByFileKey.get(declarationModuleKey);
|
|
2789
|
+
if (declarationSourceIndex) {
|
|
2790
|
+
const registered = registerSourceTypeImportCandidates(declarationSourceIndex, declarationModuleKey, declarationModule.filePath);
|
|
2791
|
+
if (!registered.ok)
|
|
2792
|
+
return registered;
|
|
2793
|
+
}
|
|
1764
2794
|
if (exportKind.value === "typeAlias" &&
|
|
1765
2795
|
declaration.kind === "typeAliasDeclaration" &&
|
|
1766
2796
|
declaration.type.kind !== "objectType") {
|
|
@@ -1812,6 +2842,18 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1812
2842
|
symbol.kind === "interface" ||
|
|
1813
2843
|
symbol.kind === "enum" ||
|
|
1814
2844
|
symbol.kind === "typeAlias") {
|
|
2845
|
+
if (symbol.declaringNamespace !== namespace) {
|
|
2846
|
+
registerCrossNamespaceReexport({
|
|
2847
|
+
declaringNamespace: symbol.declaringNamespace,
|
|
2848
|
+
exportName: symbol.exportName,
|
|
2849
|
+
localName: symbol.localName,
|
|
2850
|
+
kind: symbol.kind === "interface" || symbol.kind === "typeAlias"
|
|
2851
|
+
? "type"
|
|
2852
|
+
: "value",
|
|
2853
|
+
});
|
|
2854
|
+
registerCrossNamespaceTypeDeclaration(symbol);
|
|
2855
|
+
continue;
|
|
2856
|
+
}
|
|
1815
2857
|
if (symbol.kind === "typeAlias" &&
|
|
1816
2858
|
symbol.declaration.kind === "typeAliasDeclaration" &&
|
|
1817
2859
|
symbol.declaration.type.kind !== "objectType") {
|
|
@@ -1824,11 +2866,45 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1824
2866
|
}
|
|
1825
2867
|
}
|
|
1826
2868
|
if (symbol.kind === "function") {
|
|
2869
|
+
if (symbol.declaringNamespace !== namespace) {
|
|
2870
|
+
registerCrossNamespaceReexport({
|
|
2871
|
+
declaringNamespace: symbol.declaringNamespace,
|
|
2872
|
+
exportName: symbol.exportName,
|
|
2873
|
+
localName: symbol.localName,
|
|
2874
|
+
kind: "value",
|
|
2875
|
+
});
|
|
2876
|
+
}
|
|
1827
2877
|
const functionDeclaration = symbol.declaration.kind === "functionDeclaration"
|
|
1828
2878
|
? symbol.declaration
|
|
1829
2879
|
: undefined;
|
|
1830
2880
|
if (!functionDeclaration)
|
|
1831
2881
|
continue;
|
|
2882
|
+
const symbolModuleKey = normalizeModuleFileKey(symbol.declaringFilePath);
|
|
2883
|
+
const symbolSourceIndex = sourceIndexByFileKey.get(symbolModuleKey);
|
|
2884
|
+
const symbolDeclarationModule = modulesByFileKey.get(symbolModuleKey);
|
|
2885
|
+
if (!symbolDeclarationModule) {
|
|
2886
|
+
return {
|
|
2887
|
+
ok: false,
|
|
2888
|
+
error: `Unable to resolve declaring module for '${symbol.exportName}' while generating ${symbol.declaringFilePath}.\n` +
|
|
2889
|
+
"First-party bindings generation requires a stable source module for each exported value.",
|
|
2890
|
+
};
|
|
2891
|
+
}
|
|
2892
|
+
if (symbolSourceIndex) {
|
|
2893
|
+
const registered = registerSourceTypeImportCandidates(symbolSourceIndex, symbolModuleKey, symbol.declaringFilePath);
|
|
2894
|
+
if (!registered.ok)
|
|
2895
|
+
return registered;
|
|
2896
|
+
}
|
|
2897
|
+
const registeredLocalTypeRefs = registerFacadeLocalTypeReferenceImports({
|
|
2898
|
+
declarationModule: symbolDeclarationModule,
|
|
2899
|
+
declarationNamespace: symbol.declaringNamespace,
|
|
2900
|
+
declarationFilePath: symbol.declaringFilePath,
|
|
2901
|
+
sourceIndex: symbolSourceIndex,
|
|
2902
|
+
typeParameters: functionDeclaration.typeParameters,
|
|
2903
|
+
parameterTypes: functionDeclaration.parameters.map((parameter) => parameter.type),
|
|
2904
|
+
returnType: functionDeclaration.returnType,
|
|
2905
|
+
});
|
|
2906
|
+
if (!registeredLocalTypeRefs.ok)
|
|
2907
|
+
return registeredLocalTypeRefs;
|
|
1832
2908
|
const isLocalContainerMember = symbol.declaringNamespace === module.namespace &&
|
|
1833
2909
|
symbol.declaringClassName === module.className;
|
|
1834
2910
|
if (isLocalContainerMember) {
|
|
@@ -1836,6 +2912,11 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1836
2912
|
exportName: symbol.exportName,
|
|
1837
2913
|
localName: symbol.localName,
|
|
1838
2914
|
declaration: functionDeclaration,
|
|
2915
|
+
localTypeNameRemaps: registeredLocalTypeRefs.value,
|
|
2916
|
+
sourceSignatures: sourceIndexByFileKey
|
|
2917
|
+
.get(normalizeModuleFileKey(symbol.declaringFilePath))
|
|
2918
|
+
?.exportedFunctionSignaturesByName.get(symbol.localName) ??
|
|
2919
|
+
[],
|
|
1839
2920
|
});
|
|
1840
2921
|
}
|
|
1841
2922
|
const registered = registerValueExport({
|
|
@@ -1849,6 +2930,7 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1849
2930
|
facade: {
|
|
1850
2931
|
kind: "function",
|
|
1851
2932
|
declaration: functionDeclaration,
|
|
2933
|
+
localTypeNameRemaps: registeredLocalTypeRefs.value,
|
|
1852
2934
|
sourceSignatures: sourceIndexByFileKey
|
|
1853
2935
|
.get(normalizeModuleFileKey(symbol.declaringFilePath))
|
|
1854
2936
|
?.exportedFunctionSignaturesByName.get(symbol.localName) ??
|
|
@@ -1860,13 +2942,60 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1860
2942
|
continue;
|
|
1861
2943
|
}
|
|
1862
2944
|
if (symbol.kind === "variable") {
|
|
2945
|
+
if (symbol.declaringNamespace !== namespace) {
|
|
2946
|
+
registerCrossNamespaceReexport({
|
|
2947
|
+
declaringNamespace: symbol.declaringNamespace,
|
|
2948
|
+
exportName: symbol.exportName,
|
|
2949
|
+
localName: symbol.localName,
|
|
2950
|
+
kind: "value",
|
|
2951
|
+
});
|
|
2952
|
+
}
|
|
1863
2953
|
const declaration = symbol.declaration.kind === "variableDeclaration"
|
|
1864
2954
|
? symbol.declaration
|
|
1865
2955
|
: undefined;
|
|
1866
2956
|
if (!declaration)
|
|
1867
2957
|
continue;
|
|
2958
|
+
const symbolModuleKey = normalizeModuleFileKey(symbol.declaringFilePath);
|
|
2959
|
+
const symbolSourceIndex = sourceIndexByFileKey.get(symbolModuleKey);
|
|
2960
|
+
const symbolDeclarationModule = modulesByFileKey.get(symbolModuleKey);
|
|
2961
|
+
if (!symbolDeclarationModule) {
|
|
2962
|
+
return {
|
|
2963
|
+
ok: false,
|
|
2964
|
+
error: `Unable to resolve declaring module for '${symbol.exportName}' while generating ${symbol.declaringFilePath}.\n` +
|
|
2965
|
+
"First-party bindings generation requires a stable source module for each exported value.",
|
|
2966
|
+
};
|
|
2967
|
+
}
|
|
2968
|
+
if (symbolSourceIndex) {
|
|
2969
|
+
const registered = registerSourceTypeImportCandidates(symbolSourceIndex, symbolModuleKey, symbol.declaringFilePath);
|
|
2970
|
+
if (!registered.ok)
|
|
2971
|
+
return registered;
|
|
2972
|
+
}
|
|
1868
2973
|
const declarator = declaration.declarations.find((candidate) => candidate.name.kind === "identifierPattern" &&
|
|
1869
2974
|
candidate.name.name === symbol.localName);
|
|
2975
|
+
const exportDeclarator = declarator && declarator.name.kind === "identifierPattern"
|
|
2976
|
+
? {
|
|
2977
|
+
kind: declarator.kind,
|
|
2978
|
+
name: declarator.name,
|
|
2979
|
+
type: declarator.type,
|
|
2980
|
+
initializer: declarator.initializer,
|
|
2981
|
+
}
|
|
2982
|
+
: undefined;
|
|
2983
|
+
const exportedFunctionType = resolveFunctionTypeFromValueDeclarator(exportDeclarator);
|
|
2984
|
+
const registeredLocalTypeRefs = registerFacadeLocalTypeReferenceImports({
|
|
2985
|
+
declarationModule: symbolDeclarationModule,
|
|
2986
|
+
declarationNamespace: symbol.declaringNamespace,
|
|
2987
|
+
declarationFilePath: symbol.declaringFilePath,
|
|
2988
|
+
sourceIndex: symbolSourceIndex,
|
|
2989
|
+
typeParameters: undefined,
|
|
2990
|
+
parameterTypes: exportedFunctionType
|
|
2991
|
+
? [exportedFunctionType]
|
|
2992
|
+
: declarator?.type
|
|
2993
|
+
? [declarator.type]
|
|
2994
|
+
: [],
|
|
2995
|
+
returnType: undefined,
|
|
2996
|
+
});
|
|
2997
|
+
if (!registeredLocalTypeRefs.ok)
|
|
2998
|
+
return registeredLocalTypeRefs;
|
|
1870
2999
|
const isLocalContainerMember = symbol.declaringNamespace === module.namespace &&
|
|
1871
3000
|
symbol.declaringClassName === module.className;
|
|
1872
3001
|
if (isLocalContainerMember) {
|
|
@@ -1874,32 +3003,37 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1874
3003
|
exportName: symbol.exportName,
|
|
1875
3004
|
localName: symbol.localName,
|
|
1876
3005
|
declaration,
|
|
1877
|
-
declarator:
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
3006
|
+
declarator: exportDeclarator,
|
|
3007
|
+
localTypeNameRemaps: registeredLocalTypeRefs.value,
|
|
3008
|
+
sourceType: sourceIndexByFileKey
|
|
3009
|
+
.get(normalizeModuleFileKey(symbol.declaringFilePath))
|
|
3010
|
+
?.exportedValueTypesByName.get(symbol.localName),
|
|
3011
|
+
sourceSignatures: sourceIndexByFileKey
|
|
3012
|
+
.get(normalizeModuleFileKey(symbol.declaringFilePath))
|
|
3013
|
+
?.exportedFunctionSignaturesByName.get(symbol.localName) ??
|
|
3014
|
+
[],
|
|
1884
3015
|
});
|
|
1885
3016
|
}
|
|
1886
3017
|
const registered = registerValueExport({
|
|
1887
3018
|
exportName: symbol.exportName,
|
|
1888
3019
|
binding: {
|
|
1889
|
-
kind: "field",
|
|
3020
|
+
kind: exportedFunctionType ? "functionType" : "field",
|
|
1890
3021
|
clrName: symbol.localName,
|
|
1891
3022
|
declaringClrType: toClrTypeName(symbol.declaringNamespace, symbol.declaringClassName),
|
|
1892
3023
|
declaringAssemblyName: assemblyName,
|
|
3024
|
+
semanticType: exportedFunctionType
|
|
3025
|
+
? undefined
|
|
3026
|
+
: rewriteBindingSemanticType(exportDeclarator?.type, registeredLocalTypeRefs.value),
|
|
3027
|
+
semanticSignature: exportedFunctionType
|
|
3028
|
+
? buildSemanticSignatureFromFunctionType(exportedFunctionType, registeredLocalTypeRefs.value)
|
|
3029
|
+
: undefined,
|
|
1893
3030
|
},
|
|
1894
3031
|
facade: {
|
|
1895
3032
|
kind: "variable",
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
type: declarator.type,
|
|
1901
|
-
}
|
|
1902
|
-
: undefined,
|
|
3033
|
+
localTypeNameRemaps: registeredLocalTypeRefs.value,
|
|
3034
|
+
sourceType: symbolSourceIndex?.exportedValueTypesByName.get(symbol.localName),
|
|
3035
|
+
sourceSignatures: symbolSourceIndex?.exportedFunctionSignaturesByName.get(symbol.localName) ?? [],
|
|
3036
|
+
declarator: exportDeclarator,
|
|
1903
3037
|
},
|
|
1904
3038
|
});
|
|
1905
3039
|
if (!registered.ok)
|
|
@@ -1914,18 +3048,114 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1914
3048
|
});
|
|
1915
3049
|
}
|
|
1916
3050
|
}
|
|
3051
|
+
const anonymousHelperClassNamesByShape = new Map();
|
|
3052
|
+
const registerAnonymousHelperClass = (emittedName, declaration) => {
|
|
3053
|
+
if (!emittedName.startsWith("__Anon_") &&
|
|
3054
|
+
!declaration.name.startsWith("__Anon_")) {
|
|
3055
|
+
return;
|
|
3056
|
+
}
|
|
3057
|
+
const members = [];
|
|
3058
|
+
for (const member of declaration.members) {
|
|
3059
|
+
if (member.kind === "propertyDeclaration") {
|
|
3060
|
+
if (isPortableMarkerMemberName(member.name))
|
|
3061
|
+
continue;
|
|
3062
|
+
members.push({
|
|
3063
|
+
kind: "propertySignature",
|
|
3064
|
+
name: member.name,
|
|
3065
|
+
type: member.type ?? { kind: "unknownType" },
|
|
3066
|
+
isOptional: false,
|
|
3067
|
+
isReadonly: member.isReadonly,
|
|
3068
|
+
});
|
|
3069
|
+
continue;
|
|
3070
|
+
}
|
|
3071
|
+
if (member.kind === "methodDeclaration") {
|
|
3072
|
+
if (isPortableMarkerMemberName(member.name))
|
|
3073
|
+
continue;
|
|
3074
|
+
members.push({
|
|
3075
|
+
kind: "methodSignature",
|
|
3076
|
+
name: member.name,
|
|
3077
|
+
parameters: member.parameters,
|
|
3078
|
+
returnType: member.returnType,
|
|
3079
|
+
typeParameters: member.typeParameters,
|
|
3080
|
+
});
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
3083
|
+
const shape = renderPortableType({ kind: "objectType", members }, declaration.typeParameters?.map((typeParameter) => typeParameter.name) ??
|
|
3084
|
+
[], new Map(), new Map());
|
|
3085
|
+
anonymousHelperClassNamesByShape.set(shape, emittedName);
|
|
3086
|
+
};
|
|
3087
|
+
for (const symbol of typeDeclarations) {
|
|
3088
|
+
if (symbol.kind === "class" &&
|
|
3089
|
+
symbol.declaration.kind === "classDeclaration") {
|
|
3090
|
+
registerAnonymousHelperClass(symbol.localName, symbol.declaration);
|
|
3091
|
+
}
|
|
3092
|
+
}
|
|
3093
|
+
for (const helper of internalHelperTypeDeclarationsByKey.values()) {
|
|
3094
|
+
if (helper.kind === "class") {
|
|
3095
|
+
registerAnonymousHelperClass(helper.emittedName, helper.declaration);
|
|
3096
|
+
}
|
|
3097
|
+
}
|
|
3098
|
+
for (const [moduleKey, sourceIndex] of sourceIndexByFileKey) {
|
|
3099
|
+
const sourceModule = modulesByFileKey.get(moduleKey);
|
|
3100
|
+
if (!sourceModule)
|
|
3101
|
+
continue;
|
|
3102
|
+
for (const [shape, anonymousType] of sourceIndex.anonymousTypeLiteralsByShape) {
|
|
3103
|
+
const className = anonymousHelperClassNamesByShape.get(shape);
|
|
3104
|
+
if (!className)
|
|
3105
|
+
continue;
|
|
3106
|
+
for (const [memberName, sourceMember] of anonymousType.members) {
|
|
3107
|
+
const wrappersResult = collectExtensionWrapperImportsFromSourceType({
|
|
3108
|
+
startModuleKey: moduleKey,
|
|
3109
|
+
typeNode: sourceMember.typeNode,
|
|
3110
|
+
sourceIndexByFileKey,
|
|
3111
|
+
modulesByFileKey,
|
|
3112
|
+
});
|
|
3113
|
+
if (!wrappersResult.ok)
|
|
3114
|
+
return wrappersResult;
|
|
3115
|
+
const wrappers = wrappersResult.value;
|
|
3116
|
+
const canUseSourceTypeText = !typeNodeUsesImportedTypeNames(sourceMember.typeNode, sourceIndex.typeImportsByLocalName);
|
|
3117
|
+
if (!canUseSourceTypeText &&
|
|
3118
|
+
wrappers.length === 0 &&
|
|
3119
|
+
!sourceMember.isOptional) {
|
|
3120
|
+
continue;
|
|
3121
|
+
}
|
|
3122
|
+
const wrapperRegistered = registerWrapperImports(wrappers, sourceModule.filePath);
|
|
3123
|
+
if (!wrapperRegistered.ok)
|
|
3124
|
+
return wrapperRegistered;
|
|
3125
|
+
memberOverrides.push({
|
|
3126
|
+
className,
|
|
3127
|
+
memberName,
|
|
3128
|
+
sourceTypeText: canUseSourceTypeText
|
|
3129
|
+
? sourceMember.typeText
|
|
3130
|
+
: undefined,
|
|
3131
|
+
replaceWithSourceType: canUseSourceTypeText,
|
|
3132
|
+
isOptional: sourceMember.isOptional,
|
|
3133
|
+
emitOptionalPropertySyntax: true,
|
|
3134
|
+
wrappers,
|
|
3135
|
+
});
|
|
3136
|
+
}
|
|
3137
|
+
}
|
|
3138
|
+
}
|
|
1917
3139
|
plans.push({
|
|
1918
3140
|
namespace,
|
|
1919
3141
|
typeDeclarations: typeDeclarations.sort((left, right) => left.exportName.localeCompare(right.exportName)),
|
|
3142
|
+
internalHelperTypeDeclarations: Array.from(internalHelperTypeDeclarationsByKey.values()).sort((left, right) => left.key.localeCompare(right.key)),
|
|
1920
3143
|
moduleContainers: moduleContainers.sort((left, right) => left.module.className.localeCompare(right.module.className)),
|
|
1921
|
-
|
|
1922
|
-
|
|
3144
|
+
crossNamespaceReexports: finalizeCrossNamespaceReexports(crossNamespaceReexportsGrouped),
|
|
3145
|
+
crossNamespaceTypeDeclarations: crossNamespaceTypeDeclarations.sort((left, right) => {
|
|
3146
|
+
const leftKey = `${left.exportName}|${left.declaringNamespace}|${left.localName}|${left.kind}`;
|
|
3147
|
+
const rightKey = `${right.exportName}|${right.declaringNamespace}|${right.localName}|${right.kind}`;
|
|
3148
|
+
return leftKey.localeCompare(rightKey);
|
|
3149
|
+
}),
|
|
3150
|
+
sourceAliases: sourceAliasPlans.sort((left, right) => left.declaration.name.localeCompare(right.declaration.name)),
|
|
1923
3151
|
memberOverrides: memberOverrides.sort((left, right) => {
|
|
1924
3152
|
const classCmp = left.className.localeCompare(right.className);
|
|
1925
3153
|
if (classCmp !== 0)
|
|
1926
3154
|
return classCmp;
|
|
1927
3155
|
return left.memberName.localeCompare(right.memberName);
|
|
1928
3156
|
}),
|
|
3157
|
+
internalTypeImports: Array.from(internalTypeImportByAlias.values()).sort((left, right) => left.localName.localeCompare(right.localName)),
|
|
3158
|
+
facadeTypeImports: Array.from(facadeTypeImportByAlias.values()).sort((left, right) => left.localName.localeCompare(right.localName)),
|
|
1929
3159
|
wrapperImports: Array.from(wrapperImportByAlias.values()).sort((left, right) => left.aliasName.localeCompare(right.aliasName)),
|
|
1930
3160
|
valueExports: Array.from(valueExportsMap.values()).sort((left, right) => left.exportName.localeCompare(right.exportName)),
|
|
1931
3161
|
});
|
|
@@ -1935,55 +3165,7 @@ const collectNamespacePlans = (modules, assemblyName, rootNamespace, sourceIndex
|
|
|
1935
3165
|
value: plans.sort((left, right) => left.namespace.localeCompare(right.namespace)),
|
|
1936
3166
|
};
|
|
1937
3167
|
};
|
|
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) => {
|
|
3168
|
+
const writeNamespaceArtifacts = (config, outDir, plan) => {
|
|
1987
3169
|
const namespacePath = moduleNamespacePath(plan.namespace);
|
|
1988
3170
|
const namespaceDir = join(outDir, namespacePath);
|
|
1989
3171
|
const internalDir = join(namespaceDir, "internal");
|
|
@@ -1992,7 +3174,8 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
|
|
|
1992
3174
|
const facadeDtsPath = join(outDir, `${namespacePath}.d.ts`);
|
|
1993
3175
|
const facadeJsPath = join(outDir, `${namespacePath}.js`);
|
|
1994
3176
|
const bindingsPath = join(namespaceDir, "bindings.json");
|
|
1995
|
-
const
|
|
3177
|
+
const anonymousStructuralAliases = buildAnonymousStructuralAliasMap(plan);
|
|
3178
|
+
const internalBodyLines = [];
|
|
1996
3179
|
const memberOverridesByClass = new Map();
|
|
1997
3180
|
for (const override of plan.memberOverrides) {
|
|
1998
3181
|
const byMember = memberOverridesByClass.get(override.className) ??
|
|
@@ -2000,47 +3183,29 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
|
|
|
2000
3183
|
byMember.set(override.memberName, override);
|
|
2001
3184
|
memberOverridesByClass.set(override.className, byMember);
|
|
2002
3185
|
}
|
|
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
3186
|
const typeBindings = [];
|
|
2022
3187
|
for (const symbol of plan.typeDeclarations) {
|
|
2023
3188
|
if (symbol.kind === "class" &&
|
|
2024
3189
|
symbol.declaration.kind === "classDeclaration") {
|
|
2025
|
-
|
|
3190
|
+
internalBodyLines.push(...renderClassInternal(symbol.declaration, plan.namespace, memberOverridesByClass.get(symbol.declaration.name) ?? new Map()));
|
|
2026
3191
|
typeBindings.push(buildTypeBindingFromClass(symbol.declaration, plan.namespace, config.outputName));
|
|
2027
3192
|
continue;
|
|
2028
3193
|
}
|
|
2029
3194
|
if (symbol.kind === "interface" &&
|
|
2030
3195
|
symbol.declaration.kind === "interfaceDeclaration") {
|
|
2031
|
-
|
|
3196
|
+
internalBodyLines.push(...renderInterfaceInternal(symbol.declaration, plan.namespace, memberOverridesByClass.get(symbol.declaration.name) ?? new Map()));
|
|
2032
3197
|
typeBindings.push(buildTypeBindingFromInterface(symbol.declaration, plan.namespace, config.outputName));
|
|
2033
3198
|
continue;
|
|
2034
3199
|
}
|
|
2035
3200
|
if (symbol.kind === "enum" &&
|
|
2036
3201
|
symbol.declaration.kind === "enumDeclaration") {
|
|
2037
|
-
|
|
3202
|
+
internalBodyLines.push(...renderEnumInternal(symbol.declaration));
|
|
2038
3203
|
typeBindings.push(buildTypeBindingFromEnum(symbol.declaration, plan.namespace, config.outputName));
|
|
2039
3204
|
continue;
|
|
2040
3205
|
}
|
|
2041
3206
|
if (symbol.kind === "typeAlias" &&
|
|
2042
3207
|
symbol.declaration.kind === "typeAliasDeclaration") {
|
|
2043
|
-
|
|
3208
|
+
internalBodyLines.push(...renderStructuralAliasInternal(symbol.declaration, plan.namespace, memberOverridesByClass.get(`${symbol.declaration.name}__Alias${(symbol.declaration.typeParameters?.length ?? 0) > 0
|
|
2044
3209
|
? `_${symbol.declaration.typeParameters?.length ?? 0}`
|
|
2045
3210
|
: ""}`) ?? new Map()));
|
|
2046
3211
|
const binding = buildTypeBindingFromStructuralAlias(symbol.declaration, plan.namespace, config.outputName);
|
|
@@ -2048,10 +3213,137 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
|
|
|
2048
3213
|
typeBindings.push(binding);
|
|
2049
3214
|
}
|
|
2050
3215
|
}
|
|
3216
|
+
const helperRemapsByModuleKey = new Map();
|
|
3217
|
+
for (const helper of plan.internalHelperTypeDeclarations) {
|
|
3218
|
+
const current = new Map(helperRemapsByModuleKey.get(helper.moduleFileKey) ?? []);
|
|
3219
|
+
current.set(helper.originalName, helper.emittedName);
|
|
3220
|
+
helperRemapsByModuleKey.set(helper.moduleFileKey, current);
|
|
3221
|
+
}
|
|
3222
|
+
for (const helper of plan.internalHelperTypeDeclarations) {
|
|
3223
|
+
const localTypeNameRemaps = helperRemapsByModuleKey.get(helper.moduleFileKey) ?? new Map();
|
|
3224
|
+
switch (helper.kind) {
|
|
3225
|
+
case "class":
|
|
3226
|
+
internalBodyLines.push(...renderClassInternal(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(buildTypeBindingFromClass(helper.declaration, helper.declaringNamespace, config.outputName, localTypeNameRemaps));
|
|
3230
|
+
continue;
|
|
3231
|
+
case "interface":
|
|
3232
|
+
internalBodyLines.push(...renderInterfaceInternal(helper.declaration, helper.declaringNamespace, memberOverridesByClass.get(helper.emittedName) ??
|
|
3233
|
+
memberOverridesByClass.get(helper.declaration.name) ??
|
|
3234
|
+
new Map(), helper.emittedName, localTypeNameRemaps, helper.declaration.name, helper.declaration.name));
|
|
3235
|
+
typeBindings.push(buildTypeBindingFromInterface(helper.declaration, helper.declaringNamespace, config.outputName, localTypeNameRemaps));
|
|
3236
|
+
continue;
|
|
3237
|
+
case "enum":
|
|
3238
|
+
internalBodyLines.push(...renderEnumInternal(helper.declaration, helper.emittedName));
|
|
3239
|
+
typeBindings.push(buildTypeBindingFromEnum(helper.declaration, helper.declaringNamespace, config.outputName));
|
|
3240
|
+
continue;
|
|
3241
|
+
case "typeAlias": {
|
|
3242
|
+
const structuralLines = renderStructuralAliasInternal(helper.declaration, helper.declaringNamespace, memberOverridesByClass.get(helper.emittedName) ??
|
|
3243
|
+
memberOverridesByClass.get(`${helper.declaration.name}__Alias${(helper.declaration.typeParameters
|
|
3244
|
+
?.length ?? 0) > 0
|
|
3245
|
+
? `_${helper.declaration
|
|
3246
|
+
.typeParameters?.length ?? 0}`
|
|
3247
|
+
: ""}`) ??
|
|
3248
|
+
new Map(), helper.emittedName, localTypeNameRemaps, `${helper.declaration.name}__Alias${(helper.declaration.typeParameters
|
|
3249
|
+
?.length ?? 0) > 0
|
|
3250
|
+
? `_${helper.declaration.typeParameters
|
|
3251
|
+
?.length ?? 0}`
|
|
3252
|
+
: ""}`, `${helper.declaration.name}__Alias${(helper.declaration.typeParameters
|
|
3253
|
+
?.length ?? 0) > 0
|
|
3254
|
+
? `_${helper.declaration.typeParameters
|
|
3255
|
+
?.length ?? 0}`
|
|
3256
|
+
: ""}`);
|
|
3257
|
+
if (structuralLines.length > 0) {
|
|
3258
|
+
internalBodyLines.push(...structuralLines);
|
|
3259
|
+
const binding = buildTypeBindingFromStructuralAlias(helper.declaration, helper.declaringNamespace, config.outputName, localTypeNameRemaps);
|
|
3260
|
+
if (binding)
|
|
3261
|
+
typeBindings.push(binding);
|
|
3262
|
+
continue;
|
|
3263
|
+
}
|
|
3264
|
+
internalBodyLines.push(...renderTypeAliasInternal(helper.declaration, helper.emittedName, localTypeNameRemaps, anonymousStructuralAliases));
|
|
3265
|
+
continue;
|
|
3266
|
+
}
|
|
3267
|
+
}
|
|
3268
|
+
}
|
|
3269
|
+
const renderedSourceAliases = plan.sourceAliases.map((sourceAliasPlan) => renderSourceAliasPlan(sourceAliasPlan, anonymousStructuralAliases));
|
|
3270
|
+
const sourceAliasLines = renderedSourceAliases.map((entry) => entry.line);
|
|
3271
|
+
const sourceAliasInternalImports = renderedSourceAliases
|
|
3272
|
+
.map((entry) => entry.internalImport)
|
|
3273
|
+
.filter((entry) => entry !== undefined)
|
|
3274
|
+
.sort((left, right) => left.localeCompare(right));
|
|
2051
3275
|
for (const container of plan.moduleContainers) {
|
|
2052
|
-
|
|
3276
|
+
internalBodyLines.push(...renderContainerInternal(container, anonymousStructuralAliases));
|
|
2053
3277
|
typeBindings.push(buildTypeBindingFromContainer(container, plan.namespace, config.outputName));
|
|
2054
3278
|
}
|
|
3279
|
+
for (const symbol of plan.crossNamespaceTypeDeclarations) {
|
|
3280
|
+
if (symbol.kind === "class" &&
|
|
3281
|
+
symbol.declaration.kind === "classDeclaration") {
|
|
3282
|
+
typeBindings.push(buildTypeBindingFromClass(symbol.declaration, symbol.declaringNamespace, config.outputName));
|
|
3283
|
+
continue;
|
|
3284
|
+
}
|
|
3285
|
+
if (symbol.kind === "interface" &&
|
|
3286
|
+
symbol.declaration.kind === "interfaceDeclaration") {
|
|
3287
|
+
typeBindings.push(buildTypeBindingFromInterface(symbol.declaration, symbol.declaringNamespace, config.outputName));
|
|
3288
|
+
continue;
|
|
3289
|
+
}
|
|
3290
|
+
if (symbol.kind === "enum" &&
|
|
3291
|
+
symbol.declaration.kind === "enumDeclaration") {
|
|
3292
|
+
typeBindings.push(buildTypeBindingFromEnum(symbol.declaration, symbol.declaringNamespace, config.outputName));
|
|
3293
|
+
continue;
|
|
3294
|
+
}
|
|
3295
|
+
if (symbol.kind === "typeAlias" &&
|
|
3296
|
+
symbol.declaration.kind === "typeAliasDeclaration") {
|
|
3297
|
+
const binding = buildTypeBindingFromStructuralAlias(symbol.declaration, symbol.declaringNamespace, config.outputName);
|
|
3298
|
+
if (binding)
|
|
3299
|
+
typeBindings.push(binding);
|
|
3300
|
+
}
|
|
3301
|
+
}
|
|
3302
|
+
const internalSourceAliasLines = sourceAliasLines.length > 0
|
|
3303
|
+
? [
|
|
3304
|
+
"",
|
|
3305
|
+
"// Tsonic source type aliases (generated)",
|
|
3306
|
+
...sourceAliasLines,
|
|
3307
|
+
"// End Tsonic source type aliases",
|
|
3308
|
+
]
|
|
3309
|
+
: [];
|
|
3310
|
+
const requiredInternalTypeImports = selectSourceTypeImportsForRenderedText([...internalSourceAliasLines, ...internalBodyLines].join("\n"), plan.internalTypeImports);
|
|
3311
|
+
const internalLines = [];
|
|
3312
|
+
internalLines.push("// Generated by Tsonic - Source bindings");
|
|
3313
|
+
internalLines.push(`// Namespace: ${plan.namespace}`);
|
|
3314
|
+
internalLines.push(`// Assembly: ${config.outputName}`);
|
|
3315
|
+
internalLines.push("");
|
|
3316
|
+
internalLines.push(primitiveImportLine);
|
|
3317
|
+
if (requiredInternalTypeImports.length > 0) {
|
|
3318
|
+
internalLines.push("");
|
|
3319
|
+
internalLines.push("// Tsonic source type imports (generated)");
|
|
3320
|
+
for (const typeImport of requiredInternalTypeImports) {
|
|
3321
|
+
if (typeImport.importedName === typeImport.localName) {
|
|
3322
|
+
internalLines.push(`import type { ${typeImport.importedName} } from '${typeImport.source}';`);
|
|
3323
|
+
continue;
|
|
3324
|
+
}
|
|
3325
|
+
internalLines.push(`import type { ${typeImport.importedName} as ${typeImport.localName} } from '${typeImport.source}';`);
|
|
3326
|
+
}
|
|
3327
|
+
internalLines.push("// End Tsonic source type imports");
|
|
3328
|
+
}
|
|
3329
|
+
if (plan.wrapperImports.length > 0) {
|
|
3330
|
+
internalLines.push("");
|
|
3331
|
+
internalLines.push("// Tsonic source member type imports (generated)");
|
|
3332
|
+
for (const wrapperImport of plan.wrapperImports) {
|
|
3333
|
+
if (wrapperImport.importedName === wrapperImport.aliasName) {
|
|
3334
|
+
internalLines.push(`import type { ${wrapperImport.importedName} } from '${wrapperImport.source}';`);
|
|
3335
|
+
continue;
|
|
3336
|
+
}
|
|
3337
|
+
internalLines.push(`import type { ${wrapperImport.importedName} as ${wrapperImport.aliasName} } from '${wrapperImport.source}';`);
|
|
3338
|
+
}
|
|
3339
|
+
internalLines.push("// End Tsonic source member type imports");
|
|
3340
|
+
}
|
|
3341
|
+
internalLines.push("");
|
|
3342
|
+
if (internalSourceAliasLines.length > 0) {
|
|
3343
|
+
internalLines.push(...internalSourceAliasLines);
|
|
3344
|
+
internalLines.push("");
|
|
3345
|
+
}
|
|
3346
|
+
internalLines.push(...internalBodyLines);
|
|
2055
3347
|
writeFileSync(internalIndexPath, internalLines.join("\n").trimEnd() + "\n", "utf-8");
|
|
2056
3348
|
const internalSpecifier = moduleNamespaceToInternalSpecifier(plan.namespace);
|
|
2057
3349
|
const facadeLines = [];
|
|
@@ -2100,9 +3392,12 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
|
|
|
2100
3392
|
localTypeImports.add(`${symbol.localName}$instance`);
|
|
2101
3393
|
}
|
|
2102
3394
|
}
|
|
2103
|
-
for (const internalImport of
|
|
3395
|
+
for (const internalImport of sourceAliasInternalImports) {
|
|
2104
3396
|
localTypeImports.add(internalImport);
|
|
2105
3397
|
}
|
|
3398
|
+
for (const helper of plan.internalHelperTypeDeclarations) {
|
|
3399
|
+
localTypeImports.add(helper.emittedName);
|
|
3400
|
+
}
|
|
2106
3401
|
if (localTypeImports.size > 0) {
|
|
2107
3402
|
facadeLines.push("");
|
|
2108
3403
|
facadeLines.push("// Tsonic source alias imports (generated)");
|
|
@@ -2111,35 +3406,53 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
|
|
|
2111
3406
|
.join(", ")} } from '${internalSpecifier}';`);
|
|
2112
3407
|
facadeLines.push("// End Tsonic source alias imports");
|
|
2113
3408
|
}
|
|
2114
|
-
if (
|
|
3409
|
+
if (sourceAliasLines.length > 0) {
|
|
2115
3410
|
facadeLines.push("");
|
|
2116
3411
|
facadeLines.push("// Tsonic source type aliases (generated)");
|
|
2117
|
-
facadeLines.push(...
|
|
3412
|
+
facadeLines.push(...sourceAliasLines);
|
|
2118
3413
|
facadeLines.push("// End Tsonic source type aliases");
|
|
2119
3414
|
}
|
|
2120
|
-
if (
|
|
3415
|
+
if (plan.crossNamespaceReexports.dtsStatements.length > 0) {
|
|
2121
3416
|
facadeLines.push("");
|
|
2122
|
-
facadeLines.push("// Tsonic
|
|
2123
|
-
facadeLines.push(...
|
|
2124
|
-
facadeLines.push("// End Tsonic
|
|
3417
|
+
facadeLines.push("// Tsonic cross-namespace re-exports (generated)");
|
|
3418
|
+
facadeLines.push(...plan.crossNamespaceReexports.dtsStatements);
|
|
3419
|
+
facadeLines.push("// End Tsonic cross-namespace re-exports");
|
|
2125
3420
|
}
|
|
2126
3421
|
for (const valueExport of plan.valueExports) {
|
|
2127
3422
|
valueBindings.set(valueExport.exportName, valueExport.binding);
|
|
2128
3423
|
if (valueExport.facade.kind === "function") {
|
|
2129
|
-
const
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
3424
|
+
const sourceSignature = renderSourceFunctionSignature({
|
|
3425
|
+
declaration: valueExport.facade.declaration,
|
|
3426
|
+
sourceSignatures: valueExport.facade.sourceSignatures ?? [],
|
|
3427
|
+
localTypeNameRemaps: valueExport.facade.localTypeNameRemaps,
|
|
3428
|
+
anonymousStructuralAliases,
|
|
3429
|
+
});
|
|
3430
|
+
facadeLines.push(sourceSignature
|
|
3431
|
+
? `export declare function ${valueExport.exportName}${sourceSignature.typeParametersText}(${sourceSignature.parametersText}): ${sourceSignature.returnTypeText};`
|
|
3432
|
+
: `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
3433
|
continue;
|
|
2135
3434
|
}
|
|
2136
|
-
|
|
3435
|
+
const sourceFunctionTypeText = renderSourceFunctionType({
|
|
3436
|
+
sourceSignatures: valueExport.facade.sourceSignatures ?? [],
|
|
3437
|
+
localTypeNameRemaps: valueExport.facade.localTypeNameRemaps,
|
|
3438
|
+
anonymousStructuralAliases,
|
|
3439
|
+
});
|
|
3440
|
+
const sourceTypeText = sourceFunctionTypeText ??
|
|
3441
|
+
renderSourceValueType(valueExport.facade.sourceType, valueExport.facade.localTypeNameRemaps, anonymousStructuralAliases);
|
|
3442
|
+
facadeLines.push(`export declare const ${valueExport.exportName}: ${sourceTypeText ??
|
|
3443
|
+
renderPortableType(valueExport.facade.declarator?.type, [], valueExport.facade.localTypeNameRemaps, anonymousStructuralAliases)};`);
|
|
3444
|
+
}
|
|
3445
|
+
const requiredFacadeTypeImports = selectSourceTypeImportsForRenderedText(facadeLines.join("\n"), plan.facadeTypeImports);
|
|
3446
|
+
if (requiredFacadeTypeImports.length > 0) {
|
|
3447
|
+
facadeLines.splice(4, 0, "", "// Tsonic source type imports (generated)", ...requiredFacadeTypeImports.map((typeImport) => typeImport.importedName === typeImport.localName
|
|
3448
|
+
? `import type { ${typeImport.importedName} } from '${typeImport.source}';`
|
|
3449
|
+
: `import type { ${typeImport.importedName} as ${typeImport.localName} } from '${typeImport.source}';`), "// End Tsonic source type imports");
|
|
2137
3450
|
}
|
|
2138
3451
|
if (plan.typeDeclarations.length === 0 &&
|
|
2139
3452
|
plan.moduleContainers.length === 0 &&
|
|
2140
3453
|
plan.valueExports.length === 0 &&
|
|
2141
|
-
|
|
2142
|
-
|
|
3454
|
+
sourceAliasLines.length === 0 &&
|
|
3455
|
+
plan.crossNamespaceReexports.dtsStatements.length === 0) {
|
|
2143
3456
|
facadeLines.push("export {};");
|
|
2144
3457
|
}
|
|
2145
3458
|
writeFileSync(facadeDtsPath, facadeLines.join("\n").trimEnd() + "\n", "utf-8");
|
|
@@ -2148,12 +3461,11 @@ const writeNamespaceArtifacts = (config, outDir, plan, entrypointReexports) => {
|
|
|
2148
3461
|
"// Generated by Tsonic - Source bindings",
|
|
2149
3462
|
"// Module Stub - Do Not Execute",
|
|
2150
3463
|
"",
|
|
2151
|
-
...(
|
|
2152
|
-
entrypointReexports.jsValueStatements.length > 0
|
|
3464
|
+
...(plan.crossNamespaceReexports.jsValueStatements.length > 0
|
|
2153
3465
|
? [
|
|
2154
|
-
"// Tsonic
|
|
2155
|
-
...
|
|
2156
|
-
"// End Tsonic
|
|
3466
|
+
"// Tsonic cross-namespace value re-exports (generated)",
|
|
3467
|
+
...plan.crossNamespaceReexports.jsValueStatements,
|
|
3468
|
+
"// End Tsonic cross-namespace value re-exports",
|
|
2157
3469
|
"",
|
|
2158
3470
|
]
|
|
2159
3471
|
: []),
|
|
@@ -2216,10 +3528,6 @@ export const generateFirstPartyLibraryBindings = (config, bindingsOutDir) => {
|
|
|
2216
3528
|
}
|
|
2217
3529
|
rmSync(bindingsOutDir, { recursive: true, force: true });
|
|
2218
3530
|
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
3531
|
const sourceIndexByFileKey = new Map();
|
|
2224
3532
|
for (const module of graphResult.value.modules) {
|
|
2225
3533
|
if (module.filePath.startsWith("__tsonic/"))
|
|
@@ -2234,13 +3542,8 @@ export const generateFirstPartyLibraryBindings = (config, bindingsOutDir) => {
|
|
|
2234
3542
|
const plansResult = collectNamespacePlans(graphResult.value.modules, config.outputName, config.rootNamespace, sourceIndexByFileKey);
|
|
2235
3543
|
if (!plansResult.ok)
|
|
2236
3544
|
return plansResult;
|
|
2237
|
-
const entrypointReexportsResult = collectEntrypointReexports(graphResult.value.entryModule, modulesByFileKey);
|
|
2238
|
-
if (!entrypointReexportsResult.ok)
|
|
2239
|
-
return entrypointReexportsResult;
|
|
2240
3545
|
for (const plan of plansResult.value) {
|
|
2241
|
-
const result = writeNamespaceArtifacts(config, bindingsOutDir, plan
|
|
2242
|
-
? entrypointReexportsResult.value
|
|
2243
|
-
: undefined);
|
|
3546
|
+
const result = writeNamespaceArtifacts(config, bindingsOutDir, plan);
|
|
2244
3547
|
if (!result.ok)
|
|
2245
3548
|
return result;
|
|
2246
3549
|
}
|