protobuf-fastdsl 0.1.6 → 0.1.9
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/index.d.ts +12 -2
- package/dist/index.js +299 -7
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -12,30 +12,40 @@ type ImportedTypeNameResolver = (name: string) => string;
|
|
|
12
12
|
*/
|
|
13
13
|
declare function typeNodeToMangledName(typeNode: ts.TypeNode, sf: ts.SourceFile, resolveImportedTypeName?: ImportedTypeNameResolver): string;
|
|
14
14
|
|
|
15
|
+
type CanonicalProtobufFn = 'protobuf_encode' | 'protobuf_decode';
|
|
16
|
+
|
|
17
|
+
interface WrapperBinding {
|
|
18
|
+
fnName: CanonicalProtobufFn;
|
|
19
|
+
typeArgIndex: number;
|
|
20
|
+
typePattern?: string;
|
|
21
|
+
typeParamNames?: string[];
|
|
22
|
+
sourceFilePath?: string;
|
|
23
|
+
}
|
|
15
24
|
interface ParsedFileEntry {
|
|
16
25
|
filePath: string;
|
|
17
26
|
concrete: ProtobufMessage[];
|
|
18
27
|
templates: Map<string, GenericProtobufTemplate>;
|
|
19
28
|
importedTypeSources: Map<string, string>;
|
|
20
29
|
resolveImportedTypeName: ImportedTypeNameResolver;
|
|
30
|
+
exportedWrappers: Map<string, WrapperBinding>;
|
|
21
31
|
}
|
|
22
32
|
interface ImportedDefinitions {
|
|
23
33
|
concrete: ProtobufMessage[];
|
|
24
34
|
templates: Map<string, GenericProtobufTemplate>;
|
|
35
|
+
wrapperBindings: Map<string, WrapperBinding>;
|
|
25
36
|
}
|
|
26
37
|
/**
|
|
27
38
|
* Resolve only the import definitions reachable from protobuf call-site roots.
|
|
28
39
|
*/
|
|
29
40
|
declare function resolveImports(code: string, importerPath: string, cache: Map<string, ParsedFileEntry>): ImportedDefinitions;
|
|
30
41
|
|
|
31
|
-
type CanonicalProtobufFn = 'protobuf_encode' | 'protobuf_decode';
|
|
32
|
-
|
|
33
42
|
/** A recorded call-site for later replacement. */
|
|
34
43
|
interface CallSiteRecord {
|
|
35
44
|
fnName: CanonicalProtobufFn;
|
|
36
45
|
exprStart: number;
|
|
37
46
|
typeArgsEnd: number;
|
|
38
47
|
firstTypeArg: ts.TypeNode;
|
|
48
|
+
typeSourceFile?: ts.SourceFile;
|
|
39
49
|
line: number;
|
|
40
50
|
column: number;
|
|
41
51
|
}
|
package/dist/index.js
CHANGED
|
@@ -252,6 +252,26 @@ function matchProtobufCallSite(node, sf, bindings, options) {
|
|
|
252
252
|
}
|
|
253
253
|
|
|
254
254
|
// src/ast/analyzer.ts
|
|
255
|
+
var syntheticTypeSourceFiles = /* @__PURE__ */ new WeakMap();
|
|
256
|
+
function getCallableName(expr) {
|
|
257
|
+
if (ts5.isIdentifier(expr)) return expr.text;
|
|
258
|
+
if (ts5.isPropertyAccessExpression(expr)) return expr.name.text;
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
function instantiateWrapperTypePattern(binding, callerTypeArgs, sf) {
|
|
262
|
+
if (!binding.typePattern || !binding.typeParamNames?.length) return callerTypeArgs[binding.typeArgIndex] ?? null;
|
|
263
|
+
let text = binding.typePattern;
|
|
264
|
+
for (let i = 0; i < binding.typeParamNames.length; i++) {
|
|
265
|
+
const arg = callerTypeArgs[i];
|
|
266
|
+
if (!arg) return null;
|
|
267
|
+
text = text.replace(new RegExp(`\\b${binding.typeParamNames[i]}\\b`, "g"), arg.getText(sf));
|
|
268
|
+
}
|
|
269
|
+
const parsed = ts5.createSourceFile("wrapper-type.ts", `type __T = ${text};`, ts5.ScriptTarget.Latest, true);
|
|
270
|
+
const stmt = parsed.statements[0];
|
|
271
|
+
if (!ts5.isTypeAliasDeclaration(stmt)) return null;
|
|
272
|
+
syntheticTypeSourceFiles.set(stmt.type, parsed);
|
|
273
|
+
return stmt.type;
|
|
274
|
+
}
|
|
255
275
|
function analyze(code, filePath, imported) {
|
|
256
276
|
const sf = ts5.createSourceFile(filePath, code, ts5.ScriptTarget.Latest, true);
|
|
257
277
|
const concrete = [];
|
|
@@ -261,6 +281,7 @@ function analyze(code, filePath, imported) {
|
|
|
261
281
|
const deferredTypeArgs = [];
|
|
262
282
|
const importBindings = collectProtobufImportBindings(sf);
|
|
263
283
|
const resolveImportedTypeName = createImportedTypeNameResolver(sf);
|
|
284
|
+
const wrapperBindings = imported?.wrapperBindings ?? /* @__PURE__ */ new Map();
|
|
264
285
|
if (imported) {
|
|
265
286
|
concrete.push(...imported.concrete);
|
|
266
287
|
for (const [k, v] of imported.templates) templates.set(k, v);
|
|
@@ -282,12 +303,33 @@ function analyze(code, filePath, imported) {
|
|
|
282
303
|
if (cs) {
|
|
283
304
|
deferredTypeArgs.push(cs.firstTypeArg);
|
|
284
305
|
callSites.push(cs);
|
|
306
|
+
} else if (node.typeArguments?.length && getCallableName(node.expression) && wrapperBindings.has(getCallableName(node.expression))) {
|
|
307
|
+
const binding = wrapperBindings.get(getCallableName(node.expression));
|
|
308
|
+
const firstTypeArg = instantiateWrapperTypePattern(binding, node.typeArguments, sf);
|
|
309
|
+
if (!firstTypeArg) {
|
|
310
|
+
ts5.forEachChild(node, visit);
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
const exprStart = node.expression.getStart(sf);
|
|
314
|
+
const lc = sf.getLineAndCharacterOfPosition(exprStart);
|
|
315
|
+
deferredTypeArgs.push(firstTypeArg);
|
|
316
|
+
callSites.push({
|
|
317
|
+
fnName: binding.fnName,
|
|
318
|
+
exprStart,
|
|
319
|
+
typeArgsEnd: node.typeArguments.end + 1,
|
|
320
|
+
firstTypeArg,
|
|
321
|
+
typeSourceFile: syntheticTypeSourceFiles.get(firstTypeArg),
|
|
322
|
+
line: lc.line + 1,
|
|
323
|
+
column: lc.character + 1
|
|
324
|
+
});
|
|
285
325
|
}
|
|
286
326
|
}
|
|
287
327
|
ts5.forEachChild(node, visit);
|
|
288
328
|
});
|
|
289
329
|
for (const typeArg of deferredTypeArgs) {
|
|
290
|
-
|
|
330
|
+
const typeSf = syntheticTypeSourceFiles.get(typeArg) ?? sf;
|
|
331
|
+
const typeResolver = createImportedTypeNameResolver(typeSf);
|
|
332
|
+
monomorphizeTypeNode(typeArg, typeSf, templates, mono, typeResolver);
|
|
291
333
|
}
|
|
292
334
|
for (const m of mono.values()) concrete.push(m);
|
|
293
335
|
const names = new Set(concrete.map((m) => m.name));
|
|
@@ -313,7 +355,8 @@ function selectUsedRegistry(registry, callSites, sourceFile) {
|
|
|
313
355
|
const resolved = [];
|
|
314
356
|
const resolveImportedTypeName = createImportedTypeNameResolver(sourceFile);
|
|
315
357
|
for (const cs of callSites) {
|
|
316
|
-
const
|
|
358
|
+
const typeSf = cs.typeSourceFile ?? syntheticTypeSourceFiles.get(cs.firstTypeArg) ?? sourceFile;
|
|
359
|
+
const typeName = typeNodeToMangledName(cs.firstTypeArg, typeSf, createImportedTypeNameResolver(typeSf));
|
|
317
360
|
if (!registry.has(typeName)) continue;
|
|
318
361
|
roots.add(typeName);
|
|
319
362
|
resolved.push({ ...cs, typeName });
|
|
@@ -390,6 +433,11 @@ function replaceCallSites(code, registry) {
|
|
|
390
433
|
import ts7 from "typescript";
|
|
391
434
|
import { readFileSync, existsSync } from "fs";
|
|
392
435
|
import { dirname, resolve } from "path";
|
|
436
|
+
function getCallableName2(expr) {
|
|
437
|
+
if (ts7.isIdentifier(expr)) return expr.text;
|
|
438
|
+
if (ts7.isPropertyAccessExpression(expr)) return expr.name.text;
|
|
439
|
+
return null;
|
|
440
|
+
}
|
|
393
441
|
function extractImports(sf) {
|
|
394
442
|
const result = [];
|
|
395
443
|
for (const stmt of sf.statements) {
|
|
@@ -402,6 +450,7 @@ function extractImports(sf) {
|
|
|
402
450
|
for (const el of clause.namedBindings.elements) {
|
|
403
451
|
result.push({
|
|
404
452
|
importedName: (el.propertyName ?? el.name).text,
|
|
453
|
+
localName: el.name.text,
|
|
405
454
|
specifier
|
|
406
455
|
});
|
|
407
456
|
}
|
|
@@ -420,6 +469,190 @@ function resolveModulePath(specifier, importerPath) {
|
|
|
420
469
|
if (existsSync(indexTs)) return indexTs;
|
|
421
470
|
return null;
|
|
422
471
|
}
|
|
472
|
+
function hasExportModifier(node) {
|
|
473
|
+
return ts7.canHaveModifiers(node) && !!ts7.getModifiers(node)?.some((m) => m.kind === ts7.SyntaxKind.ExportKeyword);
|
|
474
|
+
}
|
|
475
|
+
function matchForwardedProtobufFn(body, sf, typeParams) {
|
|
476
|
+
if (!body || !typeParams?.length) return null;
|
|
477
|
+
const typeParamIndexes = new Map(typeParams.map((p, index) => [p.name.text, index]));
|
|
478
|
+
const typeParamNames = typeParams.map((p) => p.name.text);
|
|
479
|
+
const bindings = collectProtobufImportBindings(sf);
|
|
480
|
+
let found = null;
|
|
481
|
+
function visit(node) {
|
|
482
|
+
if (found) return;
|
|
483
|
+
if (ts7.isCallExpression(node)) {
|
|
484
|
+
const cs = matchProtobufCallSite(node, sf, bindings, {
|
|
485
|
+
allowLegacyUnboundCanonical: true
|
|
486
|
+
});
|
|
487
|
+
if (cs && ts7.isTypeReferenceNode(cs.firstTypeArg) && ts7.isIdentifier(cs.firstTypeArg.typeName) && typeParamIndexes.has(cs.firstTypeArg.typeName.text)) {
|
|
488
|
+
found = {
|
|
489
|
+
fnName: cs.fnName,
|
|
490
|
+
typeArgIndex: typeParamIndexes.get(cs.firstTypeArg.typeName.text),
|
|
491
|
+
sourceFilePath: sf.fileName
|
|
492
|
+
};
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
if (cs && containsTypeParameter(cs.firstTypeArg, typeParamIndexes)) {
|
|
496
|
+
found = {
|
|
497
|
+
fnName: cs.fnName,
|
|
498
|
+
typeArgIndex: firstTypeParameterIndex(cs.firstTypeArg, typeParamIndexes) ?? 0,
|
|
499
|
+
typePattern: cs.firstTypeArg.getText(sf),
|
|
500
|
+
typeParamNames,
|
|
501
|
+
sourceFilePath: sf.fileName
|
|
502
|
+
};
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
ts7.forEachChild(node, visit);
|
|
507
|
+
}
|
|
508
|
+
visit(body);
|
|
509
|
+
return found;
|
|
510
|
+
}
|
|
511
|
+
function containsTypeParameter(typeNode, typeParamIndexes) {
|
|
512
|
+
let found = false;
|
|
513
|
+
function visit(node) {
|
|
514
|
+
if (found) return;
|
|
515
|
+
if (ts7.isTypeReferenceNode(node) && ts7.isIdentifier(node.typeName) && typeParamIndexes.has(node.typeName.text)) {
|
|
516
|
+
found = true;
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
ts7.forEachChild(node, visit);
|
|
520
|
+
}
|
|
521
|
+
visit(typeNode);
|
|
522
|
+
return found;
|
|
523
|
+
}
|
|
524
|
+
function firstTypeParameterIndex(typeNode, typeParamIndexes) {
|
|
525
|
+
let index = null;
|
|
526
|
+
function visit(node) {
|
|
527
|
+
if (index !== null) return;
|
|
528
|
+
if (ts7.isTypeReferenceNode(node) && ts7.isIdentifier(node.typeName) && typeParamIndexes.has(node.typeName.text)) {
|
|
529
|
+
index = typeParamIndexes.get(node.typeName.text);
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
ts7.forEachChild(node, visit);
|
|
533
|
+
}
|
|
534
|
+
visit(typeNode);
|
|
535
|
+
return index;
|
|
536
|
+
}
|
|
537
|
+
function instantiateWrapperTypePattern2(binding, callerTypeArgs, sf) {
|
|
538
|
+
if (!binding.typePattern || !binding.typeParamNames?.length) return callerTypeArgs[binding.typeArgIndex] ?? null;
|
|
539
|
+
let text = binding.typePattern;
|
|
540
|
+
for (let i = 0; i < binding.typeParamNames.length; i++) {
|
|
541
|
+
const arg = callerTypeArgs[i];
|
|
542
|
+
if (!arg) return null;
|
|
543
|
+
text = text.replace(new RegExp(`\\b${binding.typeParamNames[i]}\\b`, "g"), arg.getText(sf));
|
|
544
|
+
}
|
|
545
|
+
const parsed = ts7.createSourceFile("wrapper-type.ts", `type __T = ${text};`, ts7.ScriptTarget.Latest, true);
|
|
546
|
+
const stmt = parsed.statements[0];
|
|
547
|
+
if (!ts7.isTypeAliasDeclaration(stmt)) return null;
|
|
548
|
+
return stmt.type;
|
|
549
|
+
}
|
|
550
|
+
function matchForwardedKnownWrapper(body, typeParams, knownWrappers) {
|
|
551
|
+
if (!body || !typeParams?.length) return null;
|
|
552
|
+
const typeParamIndexes = new Map(typeParams.map((p, index) => [p.name.text, index]));
|
|
553
|
+
let found = null;
|
|
554
|
+
function visit(node) {
|
|
555
|
+
if (found) return;
|
|
556
|
+
if (ts7.isCallExpression(node) && node.typeArguments?.length) {
|
|
557
|
+
const callableName = getCallableName2(node.expression);
|
|
558
|
+
const wrapper = callableName ? knownWrappers.get(callableName) : void 0;
|
|
559
|
+
const forwardedTypeArg = wrapper ? node.typeArguments[wrapper.typeArgIndex] : void 0;
|
|
560
|
+
if (wrapper && forwardedTypeArg && ts7.isTypeReferenceNode(forwardedTypeArg) && ts7.isIdentifier(forwardedTypeArg.typeName) && !forwardedTypeArg.typeArguments?.length && typeParamIndexes.has(forwardedTypeArg.typeName.text)) {
|
|
561
|
+
found = {
|
|
562
|
+
fnName: wrapper.fnName,
|
|
563
|
+
typeArgIndex: typeParamIndexes.get(forwardedTypeArg.typeName.text)
|
|
564
|
+
};
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
ts7.forEachChild(node, visit);
|
|
569
|
+
}
|
|
570
|
+
visit(body);
|
|
571
|
+
return found;
|
|
572
|
+
}
|
|
573
|
+
function collectWrapperCandidates(sf, exportedOnly) {
|
|
574
|
+
const candidates = [];
|
|
575
|
+
for (const stmt of sf.statements) {
|
|
576
|
+
if (ts7.isFunctionDeclaration(stmt) && stmt.name && (!exportedOnly || hasExportModifier(stmt))) {
|
|
577
|
+
candidates.push({ name: stmt.name.text, body: stmt.body, typeParameters: stmt.typeParameters });
|
|
578
|
+
continue;
|
|
579
|
+
}
|
|
580
|
+
if (!ts7.isVariableStatement(stmt) || exportedOnly && !hasExportModifier(stmt)) continue;
|
|
581
|
+
for (const decl of stmt.declarationList.declarations) {
|
|
582
|
+
if (!ts7.isIdentifier(decl.name) || !decl.initializer) continue;
|
|
583
|
+
const init = decl.initializer;
|
|
584
|
+
if (ts7.isArrowFunction(init) || ts7.isFunctionExpression(init)) {
|
|
585
|
+
candidates.push({ name: decl.name.text, body: init.body, typeParameters: init.typeParameters });
|
|
586
|
+
continue;
|
|
587
|
+
}
|
|
588
|
+
if (ts7.isObjectLiteralExpression(init)) {
|
|
589
|
+
for (const prop of init.properties) {
|
|
590
|
+
if (ts7.isPropertyAssignment(prop)) {
|
|
591
|
+
const propName = ts7.isIdentifier(prop.name) || ts7.isStringLiteral(prop.name) ? prop.name.text : null;
|
|
592
|
+
const propInit = prop.initializer;
|
|
593
|
+
if (propName && (ts7.isArrowFunction(propInit) || ts7.isFunctionExpression(propInit))) {
|
|
594
|
+
candidates.push({ name: propName, body: propInit.body, typeParameters: propInit.typeParameters });
|
|
595
|
+
}
|
|
596
|
+
continue;
|
|
597
|
+
}
|
|
598
|
+
if (ts7.isMethodDeclaration(prop)) {
|
|
599
|
+
const propName = ts7.isIdentifier(prop.name) || ts7.isStringLiteral(prop.name) ? prop.name.text : null;
|
|
600
|
+
if (propName) candidates.push({ name: propName, body: prop.body, typeParameters: prop.typeParameters });
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
return candidates;
|
|
607
|
+
}
|
|
608
|
+
function collectWrappers(sf, exportedOnly) {
|
|
609
|
+
const wrappers = /* @__PURE__ */ new Map();
|
|
610
|
+
const localWrapperMembers = /* @__PURE__ */ new Map();
|
|
611
|
+
const candidates = collectWrapperCandidates(sf, exportedOnly);
|
|
612
|
+
for (const candidate of candidates) {
|
|
613
|
+
const fn = matchForwardedProtobufFn(candidate.body, sf, candidate.typeParameters);
|
|
614
|
+
if (fn) wrappers.set(candidate.name, fn);
|
|
615
|
+
}
|
|
616
|
+
for (const candidate of candidates) {
|
|
617
|
+
if (wrappers.has(candidate.name)) continue;
|
|
618
|
+
const fn = matchForwardedKnownWrapper(candidate.body, candidate.typeParameters, wrappers);
|
|
619
|
+
if (fn) wrappers.set(candidate.name, fn);
|
|
620
|
+
}
|
|
621
|
+
for (const stmt of sf.statements) {
|
|
622
|
+
if (!ts7.isVariableStatement(stmt) || exportedOnly && !hasExportModifier(stmt)) continue;
|
|
623
|
+
for (const decl of stmt.declarationList.declarations) {
|
|
624
|
+
if (!ts7.isIdentifier(decl.name) || !decl.initializer) continue;
|
|
625
|
+
const init = decl.initializer;
|
|
626
|
+
if (ts7.isObjectLiteralExpression(init)) {
|
|
627
|
+
const memberWrappers = /* @__PURE__ */ new Map();
|
|
628
|
+
for (const prop of init.properties) {
|
|
629
|
+
if (!("name" in prop) || !prop.name) continue;
|
|
630
|
+
const propName = ts7.isIdentifier(prop.name) || ts7.isStringLiteral(prop.name) ? prop.name.text : null;
|
|
631
|
+
if (!propName) continue;
|
|
632
|
+
const fn = wrappers.get(propName);
|
|
633
|
+
if (fn) {
|
|
634
|
+
memberWrappers.set(propName, fn);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
if (memberWrappers.size) localWrapperMembers.set(decl.name.text, memberWrappers);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
for (const stmt of sf.statements) {
|
|
642
|
+
if (exportedOnly || !ts7.isVariableStatement(stmt)) continue;
|
|
643
|
+
for (const decl of stmt.declarationList.declarations) {
|
|
644
|
+
if (!ts7.isIdentifier(decl.name) || !decl.initializer || !ts7.isPropertyAccessExpression(decl.initializer)) continue;
|
|
645
|
+
if (!ts7.isIdentifier(decl.initializer.expression)) continue;
|
|
646
|
+
const memberWrappers = localWrapperMembers.get(decl.initializer.expression.text);
|
|
647
|
+
const fn = memberWrappers?.get(decl.initializer.name.text);
|
|
648
|
+
if (fn) wrappers.set(decl.name.text, fn);
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
return wrappers;
|
|
652
|
+
}
|
|
653
|
+
function collectExportedWrappers(sf) {
|
|
654
|
+
return collectWrappers(sf, true);
|
|
655
|
+
}
|
|
423
656
|
function parseFileForDefinitions(absolutePath, code) {
|
|
424
657
|
const sourceText = code ?? readFileSync(absolutePath, "utf-8");
|
|
425
658
|
const sf = ts7.createSourceFile(absolutePath, sourceText, ts7.ScriptTarget.Latest, true);
|
|
@@ -427,10 +660,12 @@ function parseFileForDefinitions(absolutePath, code) {
|
|
|
427
660
|
const templates = /* @__PURE__ */ new Map();
|
|
428
661
|
const resolveImportedTypeName = createImportedTypeNameResolver(sf);
|
|
429
662
|
const importedTypeSources = /* @__PURE__ */ new Map();
|
|
663
|
+
const exportedWrappers = collectExportedWrappers(sf);
|
|
430
664
|
for (const imp of extractImports(sf)) {
|
|
431
665
|
const resolved = resolveModulePath(imp.specifier, absolutePath);
|
|
432
666
|
if (!resolved) continue;
|
|
433
667
|
importedTypeSources.set(imp.importedName, resolved);
|
|
668
|
+
importedTypeSources.set(imp.localName, resolved);
|
|
434
669
|
}
|
|
435
670
|
for (const stmt of sf.statements) {
|
|
436
671
|
if (!ts7.isInterfaceDeclaration(stmt)) continue;
|
|
@@ -447,7 +682,8 @@ function parseFileForDefinitions(absolutePath, code) {
|
|
|
447
682
|
concrete,
|
|
448
683
|
templates,
|
|
449
684
|
importedTypeSources,
|
|
450
|
-
resolveImportedTypeName
|
|
685
|
+
resolveImportedTypeName,
|
|
686
|
+
exportedWrappers
|
|
451
687
|
};
|
|
452
688
|
}
|
|
453
689
|
function collectCallRootTypeNodes(sf) {
|
|
@@ -472,6 +708,7 @@ function resolveImports(code, importerPath, cache) {
|
|
|
472
708
|
const fileEntries = /* @__PURE__ */ new Map([[entryPath, entry]]);
|
|
473
709
|
const visitedConcrete = /* @__PURE__ */ new Set();
|
|
474
710
|
const visitedTemplates = /* @__PURE__ */ new Set();
|
|
711
|
+
const importedObjectWrapperMembers = /* @__PURE__ */ new Map();
|
|
475
712
|
function getEntry(filePath) {
|
|
476
713
|
const abs = resolve(filePath);
|
|
477
714
|
const known = fileEntries.get(abs);
|
|
@@ -484,6 +721,42 @@ function resolveImports(code, importerPath, cache) {
|
|
|
484
721
|
fileEntries.set(abs, parsed);
|
|
485
722
|
return parsed;
|
|
486
723
|
}
|
|
724
|
+
function collectCalledGenericIdentifiers(sf) {
|
|
725
|
+
const names = /* @__PURE__ */ new Set();
|
|
726
|
+
ts7.forEachChild(sf, function visit(node) {
|
|
727
|
+
if (ts7.isCallExpression(node) && node.typeArguments?.length) {
|
|
728
|
+
const callableName = getCallableName2(node.expression);
|
|
729
|
+
if (callableName) names.add(callableName);
|
|
730
|
+
}
|
|
731
|
+
ts7.forEachChild(node, visit);
|
|
732
|
+
});
|
|
733
|
+
return names;
|
|
734
|
+
}
|
|
735
|
+
function collectWrapperBindings(from, sf) {
|
|
736
|
+
const bindings = /* @__PURE__ */ new Map();
|
|
737
|
+
const localWrappers = from.filePath === entryPath ? collectWrappers(sf, false) : from.exportedWrappers;
|
|
738
|
+
for (const [name, fn] of localWrappers) bindings.set(name, fn);
|
|
739
|
+
const calledGenericIdentifiers = collectCalledGenericIdentifiers(sf);
|
|
740
|
+
for (const imp of extractImports(sf)) {
|
|
741
|
+
if (!calledGenericIdentifiers.has(imp.localName)) continue;
|
|
742
|
+
const resolved = resolveModulePath(imp.specifier, from.filePath);
|
|
743
|
+
if (!resolved) continue;
|
|
744
|
+
const wrapperFn = getEntry(resolved).exportedWrappers.get(imp.importedName);
|
|
745
|
+
if (wrapperFn) bindings.set(imp.localName, wrapperFn);
|
|
746
|
+
const importedEntry = getEntry(resolved);
|
|
747
|
+
const memberNames = [...importedEntry.exportedWrappers.keys()].filter((name) => calledGenericIdentifiers.has(name));
|
|
748
|
+
if (memberNames.length) {
|
|
749
|
+
const members = /* @__PURE__ */ new Map();
|
|
750
|
+
for (const name of memberNames) {
|
|
751
|
+
const memberBinding = importedEntry.exportedWrappers.get(name);
|
|
752
|
+
members.set(name, memberBinding);
|
|
753
|
+
bindings.set(name, memberBinding);
|
|
754
|
+
}
|
|
755
|
+
importedObjectWrapperMembers.set(imp.localName, members);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
return bindings;
|
|
759
|
+
}
|
|
487
760
|
function resolveTypeName2(typeName, from) {
|
|
488
761
|
if (typeName in PRIMITIVE_TYPE_MAP) return;
|
|
489
762
|
const concreteMsg = from.concrete.find((msg) => msg.name === typeName);
|
|
@@ -526,11 +799,30 @@ function resolveImports(code, importerPath, cache) {
|
|
|
526
799
|
resolveTypeNode(typeArg, from);
|
|
527
800
|
}
|
|
528
801
|
}
|
|
529
|
-
const rootTypeNodes = collectCallRootTypeNodes(ts7.createSourceFile(entryPath, code, ts7.ScriptTarget.Latest, true));
|
|
530
|
-
|
|
531
|
-
|
|
802
|
+
const rootTypeNodes = collectCallRootTypeNodes(ts7.createSourceFile(entryPath, code, ts7.ScriptTarget.Latest, true)).map((typeNode) => ({ typeNode, from: entry }));
|
|
803
|
+
const entrySourceFile = ts7.createSourceFile(entryPath, code, ts7.ScriptTarget.Latest, true);
|
|
804
|
+
const wrapperBindings = collectWrapperBindings(entry, entrySourceFile);
|
|
805
|
+
ts7.forEachChild(entrySourceFile, function visit(node) {
|
|
806
|
+
if (ts7.isCallExpression(node) && node.typeArguments?.length && getCallableName2(node.expression) && (wrapperBindings.has(getCallableName2(node.expression)) || ts7.isPropertyAccessExpression(node.expression) && ts7.isIdentifier(node.expression.expression) && importedObjectWrapperMembers.get(node.expression.expression.text)?.has(node.expression.name.text))) {
|
|
807
|
+
const binding = wrapperBindings.get(getCallableName2(node.expression)) ?? (ts7.isPropertyAccessExpression(node.expression) && ts7.isIdentifier(node.expression.expression) ? importedObjectWrapperMembers.get(node.expression.expression.text)?.get(node.expression.name.text) : void 0);
|
|
808
|
+
if (!binding) return;
|
|
809
|
+
const typeArg = instantiateWrapperTypePattern2(binding, node.typeArguments, entrySourceFile);
|
|
810
|
+
if (typeArg) rootTypeNodes.push({
|
|
811
|
+
typeNode: typeArg,
|
|
812
|
+
from: binding.typePattern && binding.sourceFilePath ? getEntry(binding.sourceFilePath) : entry
|
|
813
|
+
});
|
|
814
|
+
if (binding.typePattern) {
|
|
815
|
+
for (const callerTypeArg of node.typeArguments) {
|
|
816
|
+
rootTypeNodes.push({ typeNode: callerTypeArg, from: entry });
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
ts7.forEachChild(node, visit);
|
|
821
|
+
});
|
|
822
|
+
for (const root of rootTypeNodes) {
|
|
823
|
+
resolveTypeNode(root.typeNode, root.from);
|
|
532
824
|
}
|
|
533
|
-
return { concrete: [...concrete.values()], templates };
|
|
825
|
+
return { concrete: [...concrete.values()], templates, wrapperBindings };
|
|
534
826
|
}
|
|
535
827
|
|
|
536
828
|
// src/index.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "protobuf-fastdsl",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/runtime.js",
|
|
6
6
|
"types": "protobuf.d.ts",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"typescript": "^5.5.0"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0"
|
|
34
|
+
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
|
|
35
35
|
},
|
|
36
36
|
"peerDependenciesMeta": {
|
|
37
37
|
"vite": {
|