@suss/adapter-typescript 0.19.0 → 0.20.0
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.cjs +9105 -8549
- package/dist/index.d.cts +290 -119
- package/dist/index.d.ts +290 -119
- package/dist/index.js +9162 -8605
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { SourceFile, Node, FunctionDeclaration, FunctionExpression, ArrowFunction, MethodDeclaration, CallExpression, Project, Symbol, Expression, NewExpression,
|
|
2
|
-
import { PackDeclarations, TransparentWrapper, RawCondition, DiscoveryPattern, TerminalPattern, InputMappingPattern, LanguageAdapter, PatternPack, ExtractorOptions, InvocationRecognizer, AccessRecognizer, RawCodeStructure, RawTerminal, RawBranch,
|
|
1
|
+
import { SourceFile, Node, FunctionDeclaration, FunctionExpression, ArrowFunction, MethodDeclaration, CallExpression, PropertyAccessExpression, TaggedTemplateExpression, Project, ImportDeclaration, Symbol, Expression, NewExpression, Identifier } from 'ts-morph';
|
|
2
|
+
import { PackDeclarations, TransparentWrapper, RawCondition, DiscoveryPattern, TerminalPattern, InputMappingPattern, EffectArg, CallOps, LanguageAdapter, PatternPack, ExtractorOptions, InvocationRecognizer, AccessRecognizer, RawCodeStructure, RawTerminal, RawBranch, RawDeclaredContract, ContractPattern, AstCapableOps, ResponsePropertyMapping } from '@suss/extractor';
|
|
3
3
|
import { BehavioralSummary, MessageBusSemantics, DeployableUnit, BoundaryBinding, Predicate, TypeShape, ValueRef } from '@suss/behavioral-ir';
|
|
4
4
|
import { Proof, Atom } from '@suss/datalog';
|
|
5
5
|
import { ResolutionExplanation } from '@suss/resolution';
|
|
@@ -171,6 +171,13 @@ interface ExtractionReport {
|
|
|
171
171
|
* nothing. Null when the run produced summaries.
|
|
172
172
|
*/
|
|
173
173
|
emptyStage: EmptyStage | null;
|
|
174
|
+
/**
|
|
175
|
+
* Reassigned names the run stated nothing for, because control flow
|
|
176
|
+
* decides which write a reader sees. Each is a value resolution the
|
|
177
|
+
* facts decline; the count across a large corpus says whether scoped
|
|
178
|
+
* reaching definitions is worth writing.
|
|
179
|
+
*/
|
|
180
|
+
reassignedNamesUnstated: number;
|
|
174
181
|
}
|
|
175
182
|
type EmptyStage = "tsconfig" | "gateResolution" | "candidateFiles" | "discovery" | "assembly";
|
|
176
183
|
/**
|
|
@@ -238,6 +245,14 @@ declare class ResolutionStore {
|
|
|
238
245
|
private readonly fullyExtracted;
|
|
239
246
|
private readonly seededValues;
|
|
240
247
|
private readonly importedNames;
|
|
248
|
+
private readonly writtenValues;
|
|
249
|
+
private readonly importOrigins;
|
|
250
|
+
/**
|
|
251
|
+
* A file's table depends only on its re-export closure, which
|
|
252
|
+
* `collectExports` extracts whole before answering, so later
|
|
253
|
+
* extraction elsewhere cannot change an entry.
|
|
254
|
+
*/
|
|
255
|
+
private readonly exportTables;
|
|
241
256
|
/** Files the most recent wave walk entered, for the memo to keep. */
|
|
242
257
|
private lastQueryWalked;
|
|
243
258
|
private readonly declarations;
|
|
@@ -280,6 +295,36 @@ declare class ResolutionStore {
|
|
|
280
295
|
* decorators.
|
|
281
296
|
*/
|
|
282
297
|
importedNamesOf(value: Node, modules: string[]): string[];
|
|
298
|
+
/**
|
|
299
|
+
* Which module export this value comes down to, with what made it
|
|
300
|
+
* included: a value written as `createClient()` is made from the
|
|
301
|
+
* module exporting `createClient`, and a member destructured off
|
|
302
|
+
* that result is one path segment further. The module half is the
|
|
303
|
+
* specifier as the source wrote it, so a subpath import keeps its
|
|
304
|
+
* subpath.
|
|
305
|
+
*/
|
|
306
|
+
importOriginsOf(value: Node, modules: string[]): Array<{
|
|
307
|
+
module: string;
|
|
308
|
+
path: string[];
|
|
309
|
+
}>;
|
|
310
|
+
/**
|
|
311
|
+
* The batched form: one demand set, one derivation, one widening
|
|
312
|
+
* walk shared by every value. A discovery pass asks about every
|
|
313
|
+
* callee in a file, and per-value queries would re-pay demand
|
|
314
|
+
* clearing and re-derivation once per call site.
|
|
315
|
+
*/
|
|
316
|
+
importOriginsOfMany(values: readonly Node[], modules: string[]): Map<Node, Array<{
|
|
317
|
+
module: string;
|
|
318
|
+
path: string[];
|
|
319
|
+
}>>;
|
|
320
|
+
/**
|
|
321
|
+
* The node a memo shares across references: a plain name's
|
|
322
|
+
* declaration, so a hundred call sites of one import pay one walk.
|
|
323
|
+
* Anything else keys as itself, since `a.foo` and `b.foo` share a
|
|
324
|
+
* declared `foo` without sharing a value.
|
|
325
|
+
*/
|
|
326
|
+
private sharedDeclarationFor;
|
|
327
|
+
private lookupImportOrigins;
|
|
283
328
|
/**
|
|
284
329
|
* Null tells the walk to keep widening. A value that landed in a
|
|
285
330
|
* package returns empty instead, because a library's own body is not
|
|
@@ -316,6 +361,24 @@ declare class ResolutionStore {
|
|
|
316
361
|
* SDK defeats a per-file import check and does not defeat this.
|
|
317
362
|
*/
|
|
318
363
|
filesImportingTransitively(fileSets: ReadonlyArray<FileSetQuery>): ReadonlyArray<ReadonlySet<SourceFile>>;
|
|
364
|
+
/**
|
|
365
|
+
* The calls behind a receiver that `matches` accepts, walked out in
|
|
366
|
+
* waves the way every question is. The wave ends as soon as one file
|
|
367
|
+
* yields a match, and the caller applies the single-answer policy to
|
|
368
|
+
* the set; the resolution README's anchor section says why the rules
|
|
369
|
+
* cannot rank a nearer call above a farther one.
|
|
370
|
+
*/
|
|
371
|
+
anchorCallsOf(value: Node, matches: (call: Node) => boolean): Node[];
|
|
372
|
+
/**
|
|
373
|
+
* Every name a module exports and the values behind each, with
|
|
374
|
+
* re-export chains flattened by the rules. The frontier follows
|
|
375
|
+
* re-export targets only, so a barrel of barrels extracts its own
|
|
376
|
+
* chain and nothing beside it, to any depth.
|
|
377
|
+
*/
|
|
378
|
+
exportsOf(sourceFile: SourceFile): Map<string, Node[]>;
|
|
379
|
+
private collectExports;
|
|
380
|
+
/** Module keys this file re-exports from, read off its own facts. */
|
|
381
|
+
private reExportTargetsOf;
|
|
319
382
|
/**
|
|
320
383
|
* Null keeps the wave walk widening; any candidate at all ends it,
|
|
321
384
|
* since more files can only add candidates, never take one away. The
|
|
@@ -464,6 +527,11 @@ interface DiscoveredUnit {
|
|
|
464
527
|
packageName: string;
|
|
465
528
|
exportPath: string[];
|
|
466
529
|
};
|
|
530
|
+
/** A callable identity the pack stated: module and export name. */
|
|
531
|
+
functionCallInfo?: {
|
|
532
|
+
module: string;
|
|
533
|
+
exportName: string;
|
|
534
|
+
};
|
|
467
535
|
/**
|
|
468
536
|
* Populated by `decoratedRoute` discovery (NestJS-style REST
|
|
469
537
|
* controllers). The adapter uses it to build a `rest` binding
|
|
@@ -560,6 +628,127 @@ interface Timer {
|
|
|
560
628
|
*/
|
|
561
629
|
type DescentBarriers = ReadonlySet<Node>;
|
|
562
630
|
|
|
631
|
+
/**
|
|
632
|
+
* Context handed to TypeScript-adapter access recognizers: sister
|
|
633
|
+
* to TsInvocationRecognizerContext but for property-access nodes.
|
|
634
|
+
* No `extractArgs` since property accesses don't take arguments.
|
|
635
|
+
*/
|
|
636
|
+
interface TsAccessRecognizerContext {
|
|
637
|
+
/** The property-access expression itself. */
|
|
638
|
+
access: Node;
|
|
639
|
+
/** Source file the access lives in. */
|
|
640
|
+
sourceFile: SourceFile;
|
|
641
|
+
/**
|
|
642
|
+
* One-hop lookup from a written name to the value it was bound to,
|
|
643
|
+
* from the run's facts (#300). Gives null when the run has no store,
|
|
644
|
+
* and the recognizer's own pattern match runs on the raw node.
|
|
645
|
+
*/
|
|
646
|
+
resolveWrittenValue: (value: Node) => Node | null;
|
|
647
|
+
/**
|
|
648
|
+
* What a declared pack asks about this node, when the node is a call
|
|
649
|
+
* or a tagged template. This walk visits property accesses as well,
|
|
650
|
+
* and there is no call there to ask about, so a declared pack
|
|
651
|
+
* standing on one is handed nothing and matches nothing.
|
|
652
|
+
*/
|
|
653
|
+
ops?: CallOps;
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Context handed to TypeScript-adapter recognizers. Recognizers in
|
|
657
|
+
* `@suss/framework-prisma` (and other packs) receive this and use
|
|
658
|
+
* the type-checker / source-file primitives to decide whether the
|
|
659
|
+
* call site matches their semantics. `extractArgs` reuses the same
|
|
660
|
+
* `EffectArg` builder the adapter uses for `invocation` effects, so
|
|
661
|
+
* recognizers don't have to re-implement literal/object/identifier
|
|
662
|
+
* shape extraction.
|
|
663
|
+
*/
|
|
664
|
+
interface TsInvocationRecognizerContext {
|
|
665
|
+
/** The call expression itself (also passed as the first arg). */
|
|
666
|
+
call: CallExpression;
|
|
667
|
+
/** Source file the call lives in. Useful for import resolution. */
|
|
668
|
+
sourceFile: SourceFile;
|
|
669
|
+
/**
|
|
670
|
+
* Convert the call's arguments to `EffectArg[]` using the same
|
|
671
|
+
* literal / object / identifier extraction the adapter applies to
|
|
672
|
+
* `invocation` effects. Recognizers call this when they want
|
|
673
|
+
* field-level shape (e.g. Prisma's `select: { id: true }`).
|
|
674
|
+
*/
|
|
675
|
+
extractArgs(): EffectArg[];
|
|
676
|
+
/**
|
|
677
|
+
* Whether `identifier` was introduced by an import of
|
|
678
|
+
* `expectedModule`. Recognizers use this to tell a library's export
|
|
679
|
+
* apart from a local class that happens to share its name.
|
|
680
|
+
*
|
|
681
|
+
* Named, default, and namespace imports all match. So does an import
|
|
682
|
+
* through a project-local barrel that re-exports the module: the
|
|
683
|
+
* aliased symbol is still in the package that declared it.
|
|
684
|
+
*/
|
|
685
|
+
isImportedFrom(identifier: Node, expectedModule: string): boolean;
|
|
686
|
+
/**
|
|
687
|
+
* The expression `value` is written as, followed through const
|
|
688
|
+
* bindings, imports, and re-export barrels. A recognizer asks this
|
|
689
|
+
* before claiming the source does not name something:
|
|
690
|
+
*
|
|
691
|
+
* const url = "https://sqs/.../orders";
|
|
692
|
+
* client.send(new SendMessageCommand({ QueueUrl: url }));
|
|
693
|
+
*
|
|
694
|
+
* Resolving `url` gives back the string literal, and the recognizer's
|
|
695
|
+
* own pattern match runs on that. Null when the value has no written
|
|
696
|
+
* form (a parameter, a call result), which is exactly when null on the
|
|
697
|
+
* binding is correct.
|
|
698
|
+
*/
|
|
699
|
+
resolveWrittenValue(value: Node): Node | null;
|
|
700
|
+
/**
|
|
701
|
+
* What a declared pack asks about this call, in the vocabulary
|
|
702
|
+
* `@suss/extractor` defines. A pack written as a chain of data links
|
|
703
|
+
* reads only this; the members above are what a pack written as code
|
|
704
|
+
* reaches for.
|
|
705
|
+
*/
|
|
706
|
+
ops: CallOps;
|
|
707
|
+
}
|
|
708
|
+
/**
|
|
709
|
+
* Everything a recognizer may ask about one call site.
|
|
710
|
+
*
|
|
711
|
+
* A pack's tests build it here too, so a pack that passes them has run
|
|
712
|
+
* against the context extraction gives it.
|
|
713
|
+
*/
|
|
714
|
+
declare function invocationContextFor(call: CallExpression, resolveWrittenValue?: (value: Node) => Node | null, originatesFrom?: OriginatesFrom, anchorCallsOf?: AnchorCallsOf): TsInvocationRecognizerContext;
|
|
715
|
+
/**
|
|
716
|
+
* Whether a value's chain reaches the module, asked of the store. The
|
|
717
|
+
* adapter binds it; a context built bare falls back to the checker's
|
|
718
|
+
* alias resolution.
|
|
719
|
+
*/
|
|
720
|
+
type OriginatesFrom = (value: Node, module: string) => boolean;
|
|
721
|
+
/** The calls behind a value that a caller's own check accepts, from the store. */
|
|
722
|
+
type AnchorCallsOf = (value: Node, matches: (call: Node) => boolean) => Node[];
|
|
723
|
+
declare function isImportedFrom(identifier: Node, expectedModule: string, originatesFrom?: OriginatesFrom): boolean;
|
|
724
|
+
/**
|
|
725
|
+
* Whether `expectedModule` declares the method a call goes to. A pack
|
|
726
|
+
* asks this when the receiver came from somewhere the source does not
|
|
727
|
+
* spell out: `const redis = await this.getClient()` says nothing about
|
|
728
|
+
* ioredis, and the type of `redis.get` says everything.
|
|
729
|
+
*
|
|
730
|
+
* A client cached on an untyped global, `global.x || new Redis()`,
|
|
731
|
+
* types as `any`, so the method has no symbol. With `resolve` supplied,
|
|
732
|
+
* what the receiver was written as still says which library: the value
|
|
733
|
+
* comes down to a construction or a factory call of something imported
|
|
734
|
+
* from it.
|
|
735
|
+
*/
|
|
736
|
+
declare function methodDeclaredIn(callee: Node, expectedModule: string, resolve?: (value: Node) => Node | null, originatesFrom?: OriginatesFrom): boolean;
|
|
737
|
+
/** The nodes this walk stops at, which is every shape a pack can guard. */
|
|
738
|
+
type Accessed = PropertyAccessExpression | CallExpression | TaggedTemplateExpression;
|
|
739
|
+
/**
|
|
740
|
+
* What one node is handed. The ops are built on the first read rather
|
|
741
|
+
* than up front, the way the invocation walk builds them: most nodes
|
|
742
|
+
* reach no declared pack, and a pack written as code never asks.
|
|
743
|
+
*
|
|
744
|
+
* A pack's tests build it here too, so a pack that passes them has run
|
|
745
|
+
* against the context extraction gives it.
|
|
746
|
+
*/
|
|
747
|
+
declare function accessContextFor(node: Accessed, sourceFile: SourceFile, resolveWrittenValue?: (value: Node) => Node | null, originatesFrom?: OriginatesFrom, anchorCallsOf?: AnchorCallsOf): TsAccessRecognizerContext;
|
|
748
|
+
|
|
749
|
+
/** Resolves a helper callee to its declaration; the adapter binds the store's ask. */
|
|
750
|
+
type ResolveCallee = (callee: Node) => Node | null;
|
|
751
|
+
|
|
563
752
|
/**
|
|
564
753
|
* The whole extraction, from a tsconfig to a set of behavioral
|
|
565
754
|
* summaries. `createTypeScriptAdapter` is what a caller uses;
|
|
@@ -575,7 +764,7 @@ type DescentBarriers = ReadonlySet<Node>;
|
|
|
575
764
|
* framework or a runtime belongs to a pack.
|
|
576
765
|
*/
|
|
577
766
|
|
|
578
|
-
declare function extractCodeStructure(unit: DiscoveredUnit, pack: PatternPack, invocationRecognizers?: InvocationRecognizer[], accessRecognizers?: AccessRecognizer[], barriers?: DescentBarriers, resolveWrittenValue?: (value: Node) => Node | null): RawCodeStructure;
|
|
767
|
+
declare function extractCodeStructure(unit: DiscoveredUnit, pack: PatternPack, invocationRecognizers?: InvocationRecognizer[], accessRecognizers?: AccessRecognizer[], barriers?: DescentBarriers, resolveWrittenValue?: (value: Node) => Node | null, originatesFrom?: OriginatesFrom, anchorCallsOf?: AnchorCallsOf, resolveCallee?: ResolveCallee): RawCodeStructure;
|
|
579
768
|
interface TypeScriptAdapterConfig {
|
|
580
769
|
tsConfigFilePath?: string;
|
|
581
770
|
/**
|
|
@@ -639,7 +828,7 @@ interface FoundTerminal {
|
|
|
639
828
|
* discovered. Inside a nested function only escaping terminals are
|
|
640
829
|
* matched: see `NESTED_ESCAPING_MATCH_TYPES`.
|
|
641
830
|
*/
|
|
642
|
-
declare function findTerminals(func: FunctionRoot, patterns: TerminalPattern[], barriers?: DescentBarriers, resolveWrittenValue?: (value: Node) => Node | null): FoundTerminal[];
|
|
831
|
+
declare function findTerminals(func: FunctionRoot, patterns: TerminalPattern[], barriers?: DescentBarriers, resolveWrittenValue?: (value: Node) => Node | null, originatesFrom?: OriginatesFrom, resolveCallee?: ResolveCallee): FoundTerminal[];
|
|
643
832
|
|
|
644
833
|
/**
|
|
645
834
|
* Turns one function into the list of branches a summary is built from.
|
|
@@ -668,7 +857,7 @@ interface RawBranchResult {
|
|
|
668
857
|
* or when every condition on it came from an early return or throw,
|
|
669
858
|
* since those are the paths that run when no guard fired.
|
|
670
859
|
*/
|
|
671
|
-
declare function extractRawBranches(func: FunctionRoot, terminalPatterns: TerminalPattern[], invocationRecognizers?: InvocationRecognizer[], accessRecognizers?: AccessRecognizer[], barriers?: DescentBarriers, resolveWrittenValue?: (value: Node) => Node | null): RawBranchResult;
|
|
860
|
+
declare function extractRawBranches(func: FunctionRoot, terminalPatterns: TerminalPattern[], invocationRecognizers?: InvocationRecognizer[], accessRecognizers?: AccessRecognizer[], barriers?: DescentBarriers, resolveWrittenValue?: (value: Node) => Node | null, originatesFrom?: OriginatesFrom, anchorCallsOf?: AnchorCallsOf, resolveCallee?: ResolveCallee): RawBranchResult;
|
|
672
861
|
|
|
673
862
|
/**
|
|
674
863
|
* A Project covering `rootDir`, for a codebase with no tsconfig to read.
|
|
@@ -763,7 +952,7 @@ interface ContractReadResult {
|
|
|
763
952
|
* Returns null if the handler wasn't registered with a contract or the contract
|
|
764
953
|
* can't be resolved.
|
|
765
954
|
*/
|
|
766
|
-
declare function readContract(unit: DiscoveredUnit, pattern: ContractPattern, framework: string): ContractReadResult | null;
|
|
955
|
+
declare function readContract(unit: DiscoveredUnit, pattern: ContractPattern, framework: string, resolution?: ResolutionStore): ContractReadResult | null;
|
|
767
956
|
/**
|
|
768
957
|
* Resolve the contract for a consumer call site.
|
|
769
958
|
*
|
|
@@ -771,7 +960,51 @@ declare function readContract(unit: DiscoveredUnit, pattern: ContractPattern, fr
|
|
|
771
960
|
* call to find the contract, then extracts the endpoint definition for the
|
|
772
961
|
* matched method name (e.g. "getUser").
|
|
773
962
|
*/
|
|
774
|
-
declare function readContractForClientCall(callExpression: Node, methodName: string, pattern: ContractPattern, framework: string): ContractReadResult | null;
|
|
963
|
+
declare function readContractForClientCall(callExpression: Node, methodName: string, pattern: ContractPattern, framework: string, resolution?: ResolutionStore): ContractReadResult | null;
|
|
964
|
+
|
|
965
|
+
/**
|
|
966
|
+
* The one import scan.
|
|
967
|
+
*
|
|
968
|
+
* Fifteen copies of "which names did this file import from module X"
|
|
969
|
+
* grew across discovery handlers and packs, and two of them disagreed
|
|
970
|
+
* about aliases (#674). Every question about a file's imports of a
|
|
971
|
+
* module is asked here: which declarations name it, what the named
|
|
972
|
+
* imports are called locally, and which local spellings the default
|
|
973
|
+
* and namespace imports go by. Matching semantics are explicit
|
|
974
|
+
* options, so a caller that accepts subpath specifiers or resolves
|
|
975
|
+
* path-shaped specifiers through the store says so, and one that
|
|
976
|
+
* matches the specifier verbatim stays verbatim.
|
|
977
|
+
*/
|
|
978
|
+
|
|
979
|
+
interface ImportScanOptions {
|
|
980
|
+
/**
|
|
981
|
+
* Accept `module/subpath` specifiers beside the exact module, the
|
|
982
|
+
* way `react-dom/client` is still react-dom's surface.
|
|
983
|
+
*/
|
|
984
|
+
subpaths?: boolean;
|
|
985
|
+
/** Resolve path-shaped specifiers through the store's module graph. */
|
|
986
|
+
resolution?: ResolutionStore;
|
|
987
|
+
}
|
|
988
|
+
/** One named import: how the file spells it, and what it is. */
|
|
989
|
+
interface NamedImport {
|
|
990
|
+
/** The spelling this file binds, the alias when there is one. */
|
|
991
|
+
local: string;
|
|
992
|
+
/** The name the module exports it as. */
|
|
993
|
+
canonical: string;
|
|
994
|
+
/** The specifier as written, for a caller that reads sub-paths. */
|
|
995
|
+
specifier: string;
|
|
996
|
+
}
|
|
997
|
+
/** Every named import of these modules, aliases resolved. */
|
|
998
|
+
declare function namedImportsOf(sourceFile: SourceFile, modules: readonly string[], options?: ImportScanOptions): NamedImport[];
|
|
999
|
+
/**
|
|
1000
|
+
* Local spelling to canonical exported name, for every named import
|
|
1001
|
+
* of these modules. `import { Get as HttpGet }` yields HttpGet -> Get.
|
|
1002
|
+
*/
|
|
1003
|
+
declare function importedNamesOf(sourceFile: SourceFile, modules: readonly string[], options?: ImportScanOptions): Map<string, string>;
|
|
1004
|
+
/** The local spellings of default and namespace imports of these modules. */
|
|
1005
|
+
declare function importedRootsOf(sourceFile: SourceFile, modules: readonly string[], options?: ImportScanOptions): Set<string>;
|
|
1006
|
+
/** Every import declaration in the file that names one of `modules`. */
|
|
1007
|
+
declare function importDeclarationsOf(sourceFile: SourceFile, modules: readonly string[], options?: ImportScanOptions): ImportDeclaration[];
|
|
775
1008
|
|
|
776
1009
|
interface TsDiscoveryContext {
|
|
777
1010
|
/** Full filesystem path of the source file. Useful for excluding
|
|
@@ -899,14 +1132,11 @@ declare class WhySession {
|
|
|
899
1132
|
private displayPath;
|
|
900
1133
|
}
|
|
901
1134
|
|
|
902
|
-
type ExportedDeclarationMap = ReturnType<SourceFile["getExportedDeclarations"]>;
|
|
903
1135
|
/**
|
|
904
|
-
* What a module exports, by exported name.
|
|
905
|
-
*
|
|
906
|
-
* and callee resolution asks the same file the same thing once per
|
|
907
|
-
* import site.
|
|
1136
|
+
* What a module exports, by exported name. The store's rules flatten
|
|
1137
|
+
* re-export chains of any length, and the store memoizes per file.
|
|
908
1138
|
*/
|
|
909
|
-
declare function exportedDeclarationsOf(sourceFile: SourceFile):
|
|
1139
|
+
declare function exportedDeclarationsOf(sourceFile: SourceFile, resolution: ResolutionStore): Map<string, Node[]>;
|
|
910
1140
|
/**
|
|
911
1141
|
* `Symbol.getAliasedSymbol`, with the re-export chains warmed first so
|
|
912
1142
|
* that an import sitting at the top of a deep chain still resolves
|
|
@@ -1031,117 +1261,31 @@ type Called = CallExpression | NewExpression | TaggedTemplateExpression;
|
|
|
1031
1261
|
/** One-hop lookup from a written name to the value it was bound to. */
|
|
1032
1262
|
type Resolve = (value: Node) => Node | null;
|
|
1033
1263
|
/** What a declared pack can ask about one TypeScript call. */
|
|
1034
|
-
declare function callOpsFor(call: Called, resolveWrittenValue?: Resolve): AstCapableOps;
|
|
1264
|
+
declare function callOpsFor(call: Called, resolveWrittenValue?: Resolve, originatesFrom?: OriginatesFrom, anchorCallsOf?: AnchorCallsOf): AstCapableOps;
|
|
1035
1265
|
|
|
1036
1266
|
/**
|
|
1037
|
-
*
|
|
1038
|
-
* to TsInvocationRecognizerContext but for property-access nodes.
|
|
1039
|
-
* No `extractArgs` since property accesses don't take arguments.
|
|
1040
|
-
*/
|
|
1041
|
-
interface TsAccessRecognizerContext {
|
|
1042
|
-
/** The property-access expression itself. */
|
|
1043
|
-
access: Node;
|
|
1044
|
-
/** Source file the access lives in. */
|
|
1045
|
-
sourceFile: SourceFile;
|
|
1046
|
-
/**
|
|
1047
|
-
* One-hop lookup from a written name to the value it was bound to,
|
|
1048
|
-
* from the run's facts (#300). Gives null when the run has no store,
|
|
1049
|
-
* and the recognizer's own pattern match runs on the raw node.
|
|
1050
|
-
*/
|
|
1051
|
-
resolveWrittenValue: (value: Node) => Node | null;
|
|
1052
|
-
/**
|
|
1053
|
-
* What a declared pack asks about this node, when the node is a call
|
|
1054
|
-
* or a tagged template. This walk visits property accesses as well,
|
|
1055
|
-
* and there is no call there to ask about, so a declared pack
|
|
1056
|
-
* standing on one is handed nothing and matches nothing.
|
|
1057
|
-
*/
|
|
1058
|
-
ops?: CallOps;
|
|
1059
|
-
}
|
|
1060
|
-
/**
|
|
1061
|
-
* Context handed to TypeScript-adapter recognizers. Recognizers in
|
|
1062
|
-
* `@suss/framework-prisma` (and other packs) receive this and use
|
|
1063
|
-
* the type-checker / source-file primitives to decide whether the
|
|
1064
|
-
* call site matches their semantics. `extractArgs` reuses the same
|
|
1065
|
-
* `EffectArg` builder the adapter uses for `invocation` effects, so
|
|
1066
|
-
* recognizers don't have to re-implement literal/object/identifier
|
|
1067
|
-
* shape extraction.
|
|
1068
|
-
*/
|
|
1069
|
-
interface TsInvocationRecognizerContext {
|
|
1070
|
-
/** The call expression itself (also passed as the first arg). */
|
|
1071
|
-
call: CallExpression;
|
|
1072
|
-
/** Source file the call lives in. Useful for import resolution. */
|
|
1073
|
-
sourceFile: SourceFile;
|
|
1074
|
-
/**
|
|
1075
|
-
* Convert the call's arguments to `EffectArg[]` using the same
|
|
1076
|
-
* literal / object / identifier extraction the adapter applies to
|
|
1077
|
-
* `invocation` effects. Recognizers call this when they want
|
|
1078
|
-
* field-level shape (e.g. Prisma's `select: { id: true }`).
|
|
1079
|
-
*/
|
|
1080
|
-
extractArgs(): EffectArg[];
|
|
1081
|
-
/**
|
|
1082
|
-
* Whether `identifier` was introduced by an import of
|
|
1083
|
-
* `expectedModule`. Recognizers use this to tell a library's export
|
|
1084
|
-
* apart from a local class that happens to share its name.
|
|
1085
|
-
*
|
|
1086
|
-
* Named, default, and namespace imports all match. So does an import
|
|
1087
|
-
* through a project-local barrel that re-exports the module: the
|
|
1088
|
-
* aliased symbol is still in the package that declared it.
|
|
1089
|
-
*/
|
|
1090
|
-
isImportedFrom(identifier: Node, expectedModule: string): boolean;
|
|
1091
|
-
/**
|
|
1092
|
-
* The expression `value` is written as, followed through const
|
|
1093
|
-
* bindings, imports, and re-export barrels. A recognizer asks this
|
|
1094
|
-
* before claiming the source does not name something:
|
|
1095
|
-
*
|
|
1096
|
-
* const url = "https://sqs/.../orders";
|
|
1097
|
-
* client.send(new SendMessageCommand({ QueueUrl: url }));
|
|
1098
|
-
*
|
|
1099
|
-
* Resolving `url` gives back the string literal, and the recognizer's
|
|
1100
|
-
* own pattern match runs on that. Null when the value has no written
|
|
1101
|
-
* form (a parameter, a call result), which is exactly when null on the
|
|
1102
|
-
* binding is correct.
|
|
1103
|
-
*/
|
|
1104
|
-
resolveWrittenValue(value: Node): Node | null;
|
|
1105
|
-
/**
|
|
1106
|
-
* What a declared pack asks about this call, in the vocabulary
|
|
1107
|
-
* `@suss/extractor` defines. A pack written as a chain of data links
|
|
1108
|
-
* reads only this; the members above are what a pack written as code
|
|
1109
|
-
* reaches for.
|
|
1110
|
-
*/
|
|
1111
|
-
ops: CallOps;
|
|
1112
|
-
}
|
|
1113
|
-
/**
|
|
1114
|
-
* Everything a recognizer may ask about one call site.
|
|
1267
|
+
* The one resolver from a reference to the function behind it.
|
|
1115
1268
|
*
|
|
1116
|
-
*
|
|
1117
|
-
*
|
|
1269
|
+
* Four copies of "follow an identifier to its function declaration"
|
|
1270
|
+
* grew across the closure, the render-tree builder, the react pack,
|
|
1271
|
+
* and the parameter-read walk, three of them lossy (#674). The walk
|
|
1272
|
+
* lives here: alias-following through imports, shorthand properties
|
|
1273
|
+
* resolved to the binding they read, overload signatures routed to
|
|
1274
|
+
* the declaration with the body, and external code refused. Callers
|
|
1275
|
+
* that need only the file and name take `functionTargetOf`; the
|
|
1276
|
+
* closure takes `resolveDecl` for the function root itself.
|
|
1118
1277
|
*/
|
|
1119
|
-
|
|
1120
|
-
declare function isImportedFrom(identifier: Node, expectedModule: string): boolean;
|
|
1121
|
-
/**
|
|
1122
|
-
* Whether `expectedModule` declares the method a call goes to. A pack
|
|
1123
|
-
* asks this when the receiver came from somewhere the source does not
|
|
1124
|
-
* spell out: `const redis = await this.getClient()` says nothing about
|
|
1125
|
-
* ioredis, and the type of `redis.get` says everything.
|
|
1126
|
-
*
|
|
1127
|
-
* A client cached on an untyped global, `global.x || new Redis()`,
|
|
1128
|
-
* types as `any`, so the method has no symbol. With `resolve` supplied,
|
|
1129
|
-
* what the receiver was written as still says which library: the value
|
|
1130
|
-
* comes down to a construction or a factory call of something imported
|
|
1131
|
-
* from it.
|
|
1132
|
-
*/
|
|
1133
|
-
declare function methodDeclaredIn(callee: Node, expectedModule: string, resolve?: (value: Node) => Node | null): boolean;
|
|
1134
|
-
/** The nodes this walk stops at, which is every shape a pack can guard. */
|
|
1135
|
-
type Accessed = PropertyAccessExpression | CallExpression | TaggedTemplateExpression;
|
|
1278
|
+
|
|
1136
1279
|
/**
|
|
1137
|
-
*
|
|
1138
|
-
*
|
|
1139
|
-
*
|
|
1140
|
-
*
|
|
1141
|
-
* A pack's tests build it here too, so a pack that passes them has run
|
|
1142
|
-
* against the context extraction gives it.
|
|
1280
|
+
* The function an identifier refers to, as its declaration's file and
|
|
1281
|
+
* name, for joins that never walk the body. Null when the reference
|
|
1282
|
+
* does not land on a project function.
|
|
1143
1283
|
*/
|
|
1144
|
-
declare function
|
|
1284
|
+
declare function functionTargetOf(node: Identifier): {
|
|
1285
|
+
func: FunctionRoot;
|
|
1286
|
+
file: string;
|
|
1287
|
+
name: string;
|
|
1288
|
+
} | null;
|
|
1145
1289
|
|
|
1146
1290
|
/**
|
|
1147
1291
|
* What a name-valued expression says, as fixed text with a hole for
|
|
@@ -1192,6 +1336,33 @@ declare function collectClientFieldAccesses(callExpr: CallExpression, func: Node
|
|
|
1192
1336
|
end: number;
|
|
1193
1337
|
}>, responseSemantics?: ResponsePropertyMapping[]): BranchFieldAccesses[];
|
|
1194
1338
|
|
|
1339
|
+
/**
|
|
1340
|
+
* Evidence for drafting a dependency stub: every call the project
|
|
1341
|
+
* makes into a named package, grouped by the export it reaches, with
|
|
1342
|
+
* the argument shapes observed at each call site. `suss stub draft`
|
|
1343
|
+
* turns this into a stub skeleton for an author to fill in. The
|
|
1344
|
+
* package's own code is never read, only the project's calls into it,
|
|
1345
|
+
* so this works for packages whose source no adapter can parse.
|
|
1346
|
+
*/
|
|
1347
|
+
|
|
1348
|
+
interface ObservedStubCall {
|
|
1349
|
+
readonly file: string;
|
|
1350
|
+
readonly line: number;
|
|
1351
|
+
readonly args: EffectArg[];
|
|
1352
|
+
}
|
|
1353
|
+
interface StubCallEvidence {
|
|
1354
|
+
readonly exportPath: string[];
|
|
1355
|
+
readonly calls: ObservedStubCall[];
|
|
1356
|
+
}
|
|
1357
|
+
declare function stubEvidenceIn(project: Project, packageName: string, root: string): StubCallEvidence[];
|
|
1358
|
+
interface StubEvidenceOptions {
|
|
1359
|
+
packageName: string;
|
|
1360
|
+
tsConfigFilePath?: string;
|
|
1361
|
+
/** Read when no tsconfig is given. */
|
|
1362
|
+
directory?: string;
|
|
1363
|
+
}
|
|
1364
|
+
declare function stubEvidence(options: StubEvidenceOptions): StubCallEvidence[];
|
|
1365
|
+
|
|
1195
1366
|
/**
|
|
1196
1367
|
* Resolve a ts-morph Expression node to a structured ValueRef.
|
|
1197
1368
|
* Uses only expr.getSymbol()?.getDeclarations()[0] for symbol lookup ,
|
|
@@ -1330,4 +1501,4 @@ declare function computeAdapterPacksDigest(packVersions: ReadonlyArray<{
|
|
|
1330
1501
|
version?: string;
|
|
1331
1502
|
}>): string;
|
|
1332
1503
|
|
|
1333
|
-
export { ADAPTER_VERSION, type Accessed, type CacheDiagnostic, type CacheLookup, type ClientCallSite, type ConfiguredCallContext, type ConfiguredCallRead, type ConfiguredCallSpec, type ContractReadResult, type DiscoveredUnit, type EmptyStage, type ExplainCallableOptions, type ExplainStats, type ExplainedResolution, type ExtractionReport, type FoundTerminal, type FunctionRoot, type HealthCheck, type HealthViolation, type PackFunnel, type PackGradient, type ReadNameOptions, ResolutionStore, type Timer, type TimingReport, type TsDiscoveryContext, type TsInvocationRecognizerContext, type TsJsxAttributeLocation, type TsSubUnitContext, type TypeScriptAdapter, type TypeScriptAdapterConfig, type ValueLocation, type WhyExplained, WhySession, type WhySessionOptions, accessContextFor, callOpsFor, collectAncestorBranches, collectClientFieldAccesses, computeAdapterPacksDigest, computeContentHash, createProjectWithoutTsconfig, createTsDiscoveryContext, createTsSubUnitContext, createTypeScriptAdapter, discoverUnits, evaluatePackHealth, exportedDeclarationsOf, extractCodeStructure, extractRawBranches, findNearestTsconfig, findTerminals, formatPackHealth, invocationContextFor, isImportedFrom, methodDeclaredIn, parseConditionExpression, readConfiguredCall, readContract, readContractForClientCall, readName, resolveAliasedSymbol, resolveSubject, rootIdentifier, workspaceRootFor };
|
|
1504
|
+
export { ADAPTER_VERSION, type Accessed, type CacheDiagnostic, type CacheLookup, type ClientCallSite, type ConfiguredCallContext, type ConfiguredCallRead, type ConfiguredCallSpec, type ContractReadResult, type DiscoveredUnit, type EmptyStage, type ExplainCallableOptions, type ExplainStats, type ExplainedResolution, type ExtractionReport, type FoundTerminal, type FunctionRoot, type HealthCheck, type HealthViolation, type ImportScanOptions, type ObservedStubCall, type PackFunnel, type PackGradient, type ReadNameOptions, ResolutionStore, type StubCallEvidence, type StubEvidenceOptions, type Timer, type TimingReport, type TsDiscoveryContext, type TsInvocationRecognizerContext, type TsJsxAttributeLocation, type TsSubUnitContext, type TypeScriptAdapter, type TypeScriptAdapterConfig, type ValueLocation, type WhyExplained, WhySession, type WhySessionOptions, accessContextFor, callOpsFor, collectAncestorBranches, collectClientFieldAccesses, computeAdapterPacksDigest, computeContentHash, createProjectWithoutTsconfig, createTsDiscoveryContext, createTsSubUnitContext, createTypeScriptAdapter, discoverUnits, evaluatePackHealth, exportedDeclarationsOf, extractCodeStructure, extractRawBranches, findNearestTsconfig, findTerminals, formatPackHealth, functionTargetOf, importDeclarationsOf, importedNamesOf, importedRootsOf, invocationContextFor, isImportedFrom, methodDeclaredIn, namedImportsOf, parseConditionExpression, readConfiguredCall, readContract, readContractForClientCall, readName, resolveAliasedSymbol, resolveSubject, rootIdentifier, stubEvidence, stubEvidenceIn, workspaceRootFor };
|