@suss/adapter-typescript 0.19.0 → 0.21.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/README.md +3 -1
- package/dist/index.cjs +10145 -8571
- package/dist/index.d.cts +448 -167
- package/dist/index.d.ts +448 -167
- package/dist/index.js +10155 -8579
- package/package.json +7 -6
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
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, configuredCallOption, RawDeclaredContract, ContractPattern, AstCapableOps, ResponsePropertyMapping } from '@suss/extractor';
|
|
3
3
|
import { BehavioralSummary, MessageBusSemantics, DeployableUnit, BoundaryBinding, Predicate, TypeShape, ValueRef } from '@suss/behavioral-ir';
|
|
4
|
+
import { z } from 'zod';
|
|
4
5
|
import { Proof, Atom } from '@suss/datalog';
|
|
5
6
|
import { ResolutionExplanation } from '@suss/resolution';
|
|
6
7
|
|
|
@@ -140,6 +141,14 @@ interface PackFunnel {
|
|
|
140
141
|
* while this is non-empty.
|
|
141
142
|
*/
|
|
142
143
|
failures: PackFailure[];
|
|
144
|
+
/**
|
|
145
|
+
* Registration helpers this pack's config asked for that no call in
|
|
146
|
+
* the run matched. The helper belongs to the project, so a spelling
|
|
147
|
+
* that matches nothing is a config mistake with no other symptom: the
|
|
148
|
+
* routes go missing and every count reads the same as a project
|
|
149
|
+
* without them.
|
|
150
|
+
*/
|
|
151
|
+
helpersUnmatched: string[];
|
|
143
152
|
/**
|
|
144
153
|
* What the pack wrote as data rather than as code, or null for a pack
|
|
145
154
|
* written as a hand-rolled walk. This is the one thing in the funnel
|
|
@@ -171,6 +180,13 @@ interface ExtractionReport {
|
|
|
171
180
|
* nothing. Null when the run produced summaries.
|
|
172
181
|
*/
|
|
173
182
|
emptyStage: EmptyStage | null;
|
|
183
|
+
/**
|
|
184
|
+
* Reassigned names the run stated nothing for, because control flow
|
|
185
|
+
* decides which write a reader sees. Each is a value resolution the
|
|
186
|
+
* facts decline; the count across a large corpus says whether scoped
|
|
187
|
+
* reaching definitions is worth writing.
|
|
188
|
+
*/
|
|
189
|
+
reassignedNamesUnstated: number;
|
|
174
190
|
}
|
|
175
191
|
type EmptyStage = "tsconfig" | "gateResolution" | "candidateFiles" | "discovery" | "assembly";
|
|
176
192
|
/**
|
|
@@ -238,6 +254,15 @@ declare class ResolutionStore {
|
|
|
238
254
|
private readonly fullyExtracted;
|
|
239
255
|
private readonly seededValues;
|
|
240
256
|
private readonly importedNames;
|
|
257
|
+
private readonly writtenValues;
|
|
258
|
+
private readonly importOrigins;
|
|
259
|
+
private readonly subjectConstructions;
|
|
260
|
+
/**
|
|
261
|
+
* A file's table depends only on its re-export closure, which
|
|
262
|
+
* `collectExports` extracts whole before answering, so later
|
|
263
|
+
* extraction elsewhere cannot change an entry.
|
|
264
|
+
*/
|
|
265
|
+
private readonly exportTables;
|
|
241
266
|
/** Files the most recent wave walk entered, for the memo to keep. */
|
|
242
267
|
private lastQueryWalked;
|
|
243
268
|
private readonly declarations;
|
|
@@ -273,6 +298,36 @@ declare class ResolutionStore {
|
|
|
273
298
|
* GraphQL document kept in a constant in another file.
|
|
274
299
|
*/
|
|
275
300
|
resolveWrittenValue(value: Node): Node | null;
|
|
301
|
+
/**
|
|
302
|
+
* The construction behind a registration subject: the call or `new`
|
|
303
|
+
* this value is written as, kept only when its callee comes from
|
|
304
|
+
* `importModule` under `importName`. A value written as two
|
|
305
|
+
* different things comes back null, since keying a route on the
|
|
306
|
+
* wrong app is worse than not keying it.
|
|
307
|
+
*/
|
|
308
|
+
subjectConstructionOf(value: Node, importModule: string, importName: string): Node | null;
|
|
309
|
+
/**
|
|
310
|
+
* How many constructions this value was written as, which is what
|
|
311
|
+
* `subjectConstructionOf` weighed before it declined. Ask it after
|
|
312
|
+
* that call, so the walk it needs has already been paid for.
|
|
313
|
+
*/
|
|
314
|
+
subjectCandidateCountOf(value: Node, importModule: string, importName: string): number;
|
|
315
|
+
/**
|
|
316
|
+
* The single-answer policy over the written-value walk, then the
|
|
317
|
+
* origin check on the one candidate. A candidate failing the check
|
|
318
|
+
* is settled refusal rather than a reason to widen: its own file's
|
|
319
|
+
* import facts are already in, and more files only add candidates.
|
|
320
|
+
*/
|
|
321
|
+
private lookupSubjectConstruction;
|
|
322
|
+
/**
|
|
323
|
+
* Whether the construction's callee was imported from this module
|
|
324
|
+
* under this name. A default import records its name as "default",
|
|
325
|
+
* and a pack declares a default export by the local name people
|
|
326
|
+
* give it, so "default" counts when the callee is spelled with the
|
|
327
|
+
* declared name.
|
|
328
|
+
*/
|
|
329
|
+
private constructionComesFrom;
|
|
330
|
+
private calleeNameOf;
|
|
276
331
|
/**
|
|
277
332
|
* Which names from `modules` this value comes down to, either by being
|
|
278
333
|
* one of them under a local name or by calling into one. Getting
|
|
@@ -280,6 +335,36 @@ declare class ResolutionStore {
|
|
|
280
335
|
* decorators.
|
|
281
336
|
*/
|
|
282
337
|
importedNamesOf(value: Node, modules: string[]): string[];
|
|
338
|
+
/**
|
|
339
|
+
* Which module export this value comes down to, with what made it
|
|
340
|
+
* included: a value written as `createClient()` is made from the
|
|
341
|
+
* module exporting `createClient`, and a member destructured off
|
|
342
|
+
* that result is one path segment further. The module half is the
|
|
343
|
+
* specifier as the source wrote it, so a subpath import keeps its
|
|
344
|
+
* subpath.
|
|
345
|
+
*/
|
|
346
|
+
importOriginsOf(value: Node, modules: string[]): Array<{
|
|
347
|
+
module: string;
|
|
348
|
+
path: string[];
|
|
349
|
+
}>;
|
|
350
|
+
/**
|
|
351
|
+
* The batched form: one demand set, one derivation, one widening
|
|
352
|
+
* walk shared by every value. A discovery pass asks about every
|
|
353
|
+
* callee in a file, and per-value queries would re-pay demand
|
|
354
|
+
* clearing and re-derivation once per call site.
|
|
355
|
+
*/
|
|
356
|
+
importOriginsOfMany(values: readonly Node[], modules: string[]): Map<Node, Array<{
|
|
357
|
+
module: string;
|
|
358
|
+
path: string[];
|
|
359
|
+
}>>;
|
|
360
|
+
/**
|
|
361
|
+
* The node a memo shares across references: a plain name's
|
|
362
|
+
* declaration, so a hundred call sites of one import pay one walk.
|
|
363
|
+
* Anything else keys as itself, since `a.foo` and `b.foo` share a
|
|
364
|
+
* declared `foo` without sharing a value.
|
|
365
|
+
*/
|
|
366
|
+
private sharedDeclarationFor;
|
|
367
|
+
private lookupImportOrigins;
|
|
283
368
|
/**
|
|
284
369
|
* Null tells the walk to keep widening. A value that landed in a
|
|
285
370
|
* package returns empty instead, because a library's own body is not
|
|
@@ -310,12 +395,39 @@ declare class ResolutionStore {
|
|
|
310
395
|
* construction makes an instance of. The README says why.
|
|
311
396
|
*/
|
|
312
397
|
private lookupWritten;
|
|
398
|
+
/**
|
|
399
|
+
* Read these files' facts now, before anything asks a question.
|
|
400
|
+
*
|
|
401
|
+
* A query widens along the imports of the file it starts in, which
|
|
402
|
+
* is where a value's definition is. What a caller passed is the other
|
|
403
|
+
* direction, so a question about a parameter is answered only by
|
|
404
|
+
* files the walk never reaches on its own.
|
|
405
|
+
*/
|
|
406
|
+
extractFiles(sourceFiles: Iterable<SourceFile>): void;
|
|
313
407
|
/**
|
|
314
408
|
* Which of these files reach any of these packages, following
|
|
315
409
|
* project-local re-export chains. A barrel package that re-exports an
|
|
316
410
|
* SDK defeats a per-file import check and does not defeat this.
|
|
317
411
|
*/
|
|
318
412
|
filesImportingTransitively(fileSets: ReadonlyArray<FileSetQuery>): ReadonlyArray<ReadonlySet<SourceFile>>;
|
|
413
|
+
/**
|
|
414
|
+
* The calls behind a receiver that `matches` accepts, walked out in
|
|
415
|
+
* waves the way every question is. The wave ends as soon as one file
|
|
416
|
+
* yields a match, and the caller applies the single-answer policy to
|
|
417
|
+
* the set; the resolution README's anchor section says why the rules
|
|
418
|
+
* cannot rank a nearer call above a farther one.
|
|
419
|
+
*/
|
|
420
|
+
anchorCallsOf(value: Node, matches: (call: Node) => boolean): Node[];
|
|
421
|
+
/**
|
|
422
|
+
* Every name a module exports and the values behind each, with
|
|
423
|
+
* re-export chains flattened by the rules. The frontier follows
|
|
424
|
+
* re-export targets only, so a barrel of barrels extracts its own
|
|
425
|
+
* chain and nothing beside it, to any depth.
|
|
426
|
+
*/
|
|
427
|
+
exportsOf(sourceFile: SourceFile): Map<string, Node[]>;
|
|
428
|
+
private collectExports;
|
|
429
|
+
/** Module keys this file re-exports from, read off its own facts. */
|
|
430
|
+
private reExportTargetsOf;
|
|
319
431
|
/**
|
|
320
432
|
* Null keeps the wave walk widening; any candidate at all ends it,
|
|
321
433
|
* since more files can only add candidates, never take one away. The
|
|
@@ -342,6 +454,44 @@ type FunctionRoot = FunctionDeclaration | FunctionExpression | ArrowFunction | M
|
|
|
342
454
|
*/
|
|
343
455
|
declare function collectAncestorBranches(terminalNode: Node, functionRoot: FunctionRoot): RawCondition[];
|
|
344
456
|
|
|
457
|
+
/**
|
|
458
|
+
* unfollowedCall.ts: naming the calls the reachable closure stops at.
|
|
459
|
+
*
|
|
460
|
+
* The closure follows a call by resolving its callee to a function with a
|
|
461
|
+
* body. When that fails the edge is dropped, and a unit whose body is full
|
|
462
|
+
* of dropped edges produces the same empty summary as a unit that does
|
|
463
|
+
* nothing. This module says which kind of stop a call site is, and which
|
|
464
|
+
* kinds are worth leaving a gap for.
|
|
465
|
+
*
|
|
466
|
+
* The README beside this file explains where that line is drawn, and why
|
|
467
|
+
* a call into a dependency stays on the other side of it.
|
|
468
|
+
*/
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Why the walk stopped.
|
|
472
|
+
*
|
|
473
|
+
* `noBody` states a shape and nothing else: a method on an interface, an
|
|
474
|
+
* abstract method, an ambient declaration. `unsettledValue` is declared
|
|
475
|
+
* as something other than a function, with something in it that could
|
|
476
|
+
* not be read. `multipleSources` reaches two different functions, so no
|
|
477
|
+
* single body can be followed. `outsideRun` is a declaration in a
|
|
478
|
+
* dependency, whose source this run never read. `noDeclaration` is a
|
|
479
|
+
* callee nothing declares, which is what a call on an untyped value
|
|
480
|
+
* comes to. `callerSupplied` is a parameter of the function being
|
|
481
|
+
* scanned, so the call runs whatever its caller handed in.
|
|
482
|
+
* `multipleReceivers` is a registration whose receiver comes down to
|
|
483
|
+
* more than one thing, so nothing says which one it registers on.
|
|
484
|
+
*/
|
|
485
|
+
type UnfollowedReason = "noBody" | "unsettledValue" | "multipleSources" | "outsideRun" | "noDeclaration" | "callerSupplied" | "multipleReceivers";
|
|
486
|
+
/** One call the walk met and could not follow. */
|
|
487
|
+
interface UnfollowedCall {
|
|
488
|
+
/** The callee as the source writes it, `this.dao.getEditions` say. */
|
|
489
|
+
readonly callee: string;
|
|
490
|
+
readonly reason: UnfollowedReason;
|
|
491
|
+
/** How many things the walk reached where it needed one. */
|
|
492
|
+
readonly candidates?: number;
|
|
493
|
+
}
|
|
494
|
+
|
|
345
495
|
interface ClientCallSite {
|
|
346
496
|
callExpression: CallExpression;
|
|
347
497
|
/** Method name on the client object (e.g. "getUser"), null for bare calls like fetch() */
|
|
@@ -464,6 +614,11 @@ interface DiscoveredUnit {
|
|
|
464
614
|
packageName: string;
|
|
465
615
|
exportPath: string[];
|
|
466
616
|
};
|
|
617
|
+
/** A callable identity the pack stated: module and export name. */
|
|
618
|
+
functionCallInfo?: {
|
|
619
|
+
module: string;
|
|
620
|
+
exportName: string;
|
|
621
|
+
};
|
|
467
622
|
/**
|
|
468
623
|
* Populated by `decoratedRoute` discovery (NestJS-style REST
|
|
469
624
|
* controllers). The adapter uses it to build a `rest` binding
|
|
@@ -488,6 +643,19 @@ interface DiscoveredUnit {
|
|
|
488
643
|
/** Null when the pack knows the wire but not the channel on it. */
|
|
489
644
|
channel: string | null;
|
|
490
645
|
};
|
|
646
|
+
/**
|
|
647
|
+
* Populated by a pack's `discoverUnits` callback for a deployed unit
|
|
648
|
+
* nothing else routes to, which is reached by being invoked by name.
|
|
649
|
+
* The adapter builds a `unit-invocation` binding from it, which pairs
|
|
650
|
+
* with the calls that name the same unit.
|
|
651
|
+
*/
|
|
652
|
+
invocationInfo?: DeployableUnit;
|
|
653
|
+
/**
|
|
654
|
+
* Identity of the routable this unit was registered on, when a
|
|
655
|
+
* registration call put it there. What the wrapper index is keyed on,
|
|
656
|
+
* since a wrapper is registered on the routable and not on the unit.
|
|
657
|
+
*/
|
|
658
|
+
registrationSubjectId?: string;
|
|
491
659
|
/** The thing that gets deployed and runs this unit, when known. */
|
|
492
660
|
deployableUnit?: DeployableUnit;
|
|
493
661
|
/**
|
|
@@ -505,6 +673,12 @@ interface DiscoveredUnit {
|
|
|
505
673
|
* summary as an `unreadOutcome` gap.
|
|
506
674
|
*/
|
|
507
675
|
unreadBinding?: string;
|
|
676
|
+
/**
|
|
677
|
+
* A call the handler met and could not follow, which reaches the
|
|
678
|
+
* summary as an `unfollowedCall` gap beside the ones the closure
|
|
679
|
+
* walk records.
|
|
680
|
+
*/
|
|
681
|
+
unfollowed?: UnfollowedCall;
|
|
508
682
|
}
|
|
509
683
|
|
|
510
684
|
/**
|
|
@@ -529,12 +703,19 @@ interface MountPrefixIndex {
|
|
|
529
703
|
*/
|
|
530
704
|
prefixForId?(childId: string): string;
|
|
531
705
|
}
|
|
706
|
+
/**
|
|
707
|
+
* What the project helper index says it has already expanded, which the
|
|
708
|
+
* walk consults so one registration does not become two summaries.
|
|
709
|
+
*/
|
|
710
|
+
interface ExpandedRegistrations {
|
|
711
|
+
expandedAtCallSites(helper: Node, method: string): boolean;
|
|
712
|
+
}
|
|
532
713
|
|
|
533
714
|
/**
|
|
534
715
|
* Discover code units in `sourceFile` by running all patterns.
|
|
535
716
|
* Deduplicates entries with the same function node and kind.
|
|
536
717
|
*/
|
|
537
|
-
declare function discoverUnits(sourceFile: SourceFile, patterns: DiscoveryPattern[], resolution?: ResolutionStore, mountPrefixes?: MountPrefixIndex): DiscoveredUnit[];
|
|
718
|
+
declare function discoverUnits(sourceFile: SourceFile, patterns: DiscoveryPattern[], resolution?: ResolutionStore, mountPrefixes?: MountPrefixIndex, expandedElsewhere?: ExpandedRegistrations): DiscoveredUnit[];
|
|
538
719
|
|
|
539
720
|
interface TimingReport {
|
|
540
721
|
totalMs: number;
|
|
@@ -560,6 +741,127 @@ interface Timer {
|
|
|
560
741
|
*/
|
|
561
742
|
type DescentBarriers = ReadonlySet<Node>;
|
|
562
743
|
|
|
744
|
+
/**
|
|
745
|
+
* Context handed to TypeScript-adapter access recognizers: sister
|
|
746
|
+
* to TsInvocationRecognizerContext but for property-access nodes.
|
|
747
|
+
* No `extractArgs` since property accesses don't take arguments.
|
|
748
|
+
*/
|
|
749
|
+
interface TsAccessRecognizerContext {
|
|
750
|
+
/** The property-access expression itself. */
|
|
751
|
+
access: Node;
|
|
752
|
+
/** Source file the access lives in. */
|
|
753
|
+
sourceFile: SourceFile;
|
|
754
|
+
/**
|
|
755
|
+
* One-hop lookup from a written name to the value it was bound to,
|
|
756
|
+
* from the run's facts (#300). Gives null when the run has no store,
|
|
757
|
+
* and the recognizer's own pattern match runs on the raw node.
|
|
758
|
+
*/
|
|
759
|
+
resolveWrittenValue: (value: Node) => Node | null;
|
|
760
|
+
/**
|
|
761
|
+
* What a declared pack asks about this node, when the node is a call
|
|
762
|
+
* or a tagged template. This walk visits property accesses as well,
|
|
763
|
+
* and there is no call there to ask about, so a declared pack
|
|
764
|
+
* standing on one is handed nothing and matches nothing.
|
|
765
|
+
*/
|
|
766
|
+
ops?: CallOps;
|
|
767
|
+
}
|
|
768
|
+
/**
|
|
769
|
+
* Context handed to TypeScript-adapter recognizers. Recognizers in
|
|
770
|
+
* `@suss/framework-prisma` (and other packs) receive this and use
|
|
771
|
+
* the type-checker / source-file primitives to decide whether the
|
|
772
|
+
* call site matches their semantics. `extractArgs` reuses the same
|
|
773
|
+
* `EffectArg` builder the adapter uses for `invocation` effects, so
|
|
774
|
+
* recognizers don't have to re-implement literal/object/identifier
|
|
775
|
+
* shape extraction.
|
|
776
|
+
*/
|
|
777
|
+
interface TsInvocationRecognizerContext {
|
|
778
|
+
/** The call expression itself (also passed as the first arg). */
|
|
779
|
+
call: CallExpression;
|
|
780
|
+
/** Source file the call lives in. Useful for import resolution. */
|
|
781
|
+
sourceFile: SourceFile;
|
|
782
|
+
/**
|
|
783
|
+
* Convert the call's arguments to `EffectArg[]` using the same
|
|
784
|
+
* literal / object / identifier extraction the adapter applies to
|
|
785
|
+
* `invocation` effects. Recognizers call this when they want
|
|
786
|
+
* field-level shape (e.g. Prisma's `select: { id: true }`).
|
|
787
|
+
*/
|
|
788
|
+
extractArgs(): EffectArg[];
|
|
789
|
+
/**
|
|
790
|
+
* Whether `identifier` was introduced by an import of
|
|
791
|
+
* `expectedModule`. Recognizers use this to tell a library's export
|
|
792
|
+
* apart from a local class that happens to share its name.
|
|
793
|
+
*
|
|
794
|
+
* Named, default, and namespace imports all match. So does an import
|
|
795
|
+
* through a project-local barrel that re-exports the module: the
|
|
796
|
+
* aliased symbol is still in the package that declared it.
|
|
797
|
+
*/
|
|
798
|
+
isImportedFrom(identifier: Node, expectedModule: string): boolean;
|
|
799
|
+
/**
|
|
800
|
+
* The expression `value` is written as, followed through const
|
|
801
|
+
* bindings, imports, and re-export barrels. A recognizer asks this
|
|
802
|
+
* before claiming the source does not name something:
|
|
803
|
+
*
|
|
804
|
+
* const url = "https://sqs/.../orders";
|
|
805
|
+
* client.send(new SendMessageCommand({ QueueUrl: url }));
|
|
806
|
+
*
|
|
807
|
+
* Resolving `url` gives back the string literal, and the recognizer's
|
|
808
|
+
* own pattern match runs on that. Null when the value has no written
|
|
809
|
+
* form (a parameter, a call result), which is exactly when null on the
|
|
810
|
+
* binding is correct.
|
|
811
|
+
*/
|
|
812
|
+
resolveWrittenValue(value: Node): Node | null;
|
|
813
|
+
/**
|
|
814
|
+
* What a declared pack asks about this call, in the vocabulary
|
|
815
|
+
* `@suss/extractor` defines. A pack written as a chain of data links
|
|
816
|
+
* reads only this; the members above are what a pack written as code
|
|
817
|
+
* reaches for.
|
|
818
|
+
*/
|
|
819
|
+
ops: CallOps;
|
|
820
|
+
}
|
|
821
|
+
/**
|
|
822
|
+
* Everything a recognizer may ask about one call site.
|
|
823
|
+
*
|
|
824
|
+
* A pack's tests build it here too, so a pack that passes them has run
|
|
825
|
+
* against the context extraction gives it.
|
|
826
|
+
*/
|
|
827
|
+
declare function invocationContextFor(call: CallExpression, resolveWrittenValue?: (value: Node) => Node | null, originatesFrom?: OriginatesFrom, anchorCallsOf?: AnchorCallsOf): TsInvocationRecognizerContext;
|
|
828
|
+
/**
|
|
829
|
+
* Whether a value's chain reaches the module, asked of the store. The
|
|
830
|
+
* adapter binds it; a context built bare falls back to the checker's
|
|
831
|
+
* alias resolution.
|
|
832
|
+
*/
|
|
833
|
+
type OriginatesFrom = (value: Node, module: string) => boolean;
|
|
834
|
+
/** The calls behind a value that a caller's own check accepts, from the store. */
|
|
835
|
+
type AnchorCallsOf = (value: Node, matches: (call: Node) => boolean) => Node[];
|
|
836
|
+
declare function isImportedFrom(identifier: Node, expectedModule: string, originatesFrom?: OriginatesFrom): boolean;
|
|
837
|
+
/**
|
|
838
|
+
* Whether `expectedModule` declares the method a call goes to. A pack
|
|
839
|
+
* asks this when the receiver came from somewhere the source does not
|
|
840
|
+
* spell out: `const redis = await this.getClient()` says nothing about
|
|
841
|
+
* ioredis, and the type of `redis.get` says everything.
|
|
842
|
+
*
|
|
843
|
+
* A client cached on an untyped global, `global.x || new Redis()`,
|
|
844
|
+
* types as `any`, so the method has no symbol. With `resolve` supplied,
|
|
845
|
+
* what the receiver was written as still says which library: the value
|
|
846
|
+
* comes down to a construction or a factory call of something imported
|
|
847
|
+
* from it.
|
|
848
|
+
*/
|
|
849
|
+
declare function methodDeclaredIn(callee: Node, expectedModule: string, resolve?: (value: Node) => Node | null, originatesFrom?: OriginatesFrom): boolean;
|
|
850
|
+
/** The nodes this walk stops at, which is every shape a pack can guard. */
|
|
851
|
+
type Accessed = PropertyAccessExpression | CallExpression | TaggedTemplateExpression;
|
|
852
|
+
/**
|
|
853
|
+
* What one node is handed. The ops are built on the first read rather
|
|
854
|
+
* than up front, the way the invocation walk builds them: most nodes
|
|
855
|
+
* reach no declared pack, and a pack written as code never asks.
|
|
856
|
+
*
|
|
857
|
+
* A pack's tests build it here too, so a pack that passes them has run
|
|
858
|
+
* against the context extraction gives it.
|
|
859
|
+
*/
|
|
860
|
+
declare function accessContextFor(node: Accessed, sourceFile: SourceFile, resolveWrittenValue?: (value: Node) => Node | null, originatesFrom?: OriginatesFrom, anchorCallsOf?: AnchorCallsOf): TsAccessRecognizerContext;
|
|
861
|
+
|
|
862
|
+
/** Resolves a helper callee to its declaration; the adapter binds the store's ask. */
|
|
863
|
+
type ResolveCallee = (callee: Node) => Node | null;
|
|
864
|
+
|
|
563
865
|
/**
|
|
564
866
|
* The whole extraction, from a tsconfig to a set of behavioral
|
|
565
867
|
* summaries. `createTypeScriptAdapter` is what a caller uses;
|
|
@@ -575,7 +877,7 @@ type DescentBarriers = ReadonlySet<Node>;
|
|
|
575
877
|
* framework or a runtime belongs to a pack.
|
|
576
878
|
*/
|
|
577
879
|
|
|
578
|
-
declare function extractCodeStructure(unit: DiscoveredUnit, pack: PatternPack, invocationRecognizers?: InvocationRecognizer[], accessRecognizers?: AccessRecognizer[], barriers?: DescentBarriers, resolveWrittenValue?: (value: Node) => Node | null): RawCodeStructure;
|
|
880
|
+
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
881
|
interface TypeScriptAdapterConfig {
|
|
580
882
|
tsConfigFilePath?: string;
|
|
581
883
|
/**
|
|
@@ -639,7 +941,7 @@ interface FoundTerminal {
|
|
|
639
941
|
* discovered. Inside a nested function only escaping terminals are
|
|
640
942
|
* matched: see `NESTED_ESCAPING_MATCH_TYPES`.
|
|
641
943
|
*/
|
|
642
|
-
declare function findTerminals(func: FunctionRoot, patterns: TerminalPattern[], barriers?: DescentBarriers, resolveWrittenValue?: (value: Node) => Node | null): FoundTerminal[];
|
|
944
|
+
declare function findTerminals(func: FunctionRoot, patterns: TerminalPattern[], barriers?: DescentBarriers, resolveWrittenValue?: (value: Node) => Node | null, originatesFrom?: OriginatesFrom, resolveCallee?: ResolveCallee): FoundTerminal[];
|
|
643
945
|
|
|
644
946
|
/**
|
|
645
947
|
* Turns one function into the list of branches a summary is built from.
|
|
@@ -668,7 +970,7 @@ interface RawBranchResult {
|
|
|
668
970
|
* or when every condition on it came from an early return or throw,
|
|
669
971
|
* since those are the paths that run when no guard fired.
|
|
670
972
|
*/
|
|
671
|
-
declare function extractRawBranches(func: FunctionRoot, terminalPatterns: TerminalPattern[], invocationRecognizers?: InvocationRecognizer[], accessRecognizers?: AccessRecognizer[], barriers?: DescentBarriers, resolveWrittenValue?: (value: Node) => Node | null): RawBranchResult;
|
|
973
|
+
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
974
|
|
|
673
975
|
/**
|
|
674
976
|
* A Project covering `rootDir`, for a codebase with no tsconfig to read.
|
|
@@ -698,28 +1000,12 @@ declare function findNearestTsconfig(startDir: string): string | null;
|
|
|
698
1000
|
*/
|
|
699
1001
|
|
|
700
1002
|
/**
|
|
701
|
-
* A call the project has declared to be its own dispatcher.
|
|
702
|
-
*
|
|
703
|
-
*
|
|
704
|
-
*
|
|
705
|
-
* the type is the only thing stable across all three.
|
|
1003
|
+
* A call the project has declared to be its own dispatcher. The
|
|
1004
|
+
* declaration a project config is parsed against lives with the other
|
|
1005
|
+
* shared pack options, so this reader and the packs that take it under
|
|
1006
|
+
* `producers` describe one shape.
|
|
706
1007
|
*/
|
|
707
|
-
|
|
708
|
-
/** Module that declares the receiver's type. */
|
|
709
|
-
module: string;
|
|
710
|
-
/** Type name of the receiver, as exported from that module. */
|
|
711
|
-
receiver: string;
|
|
712
|
-
/** Method that performs the send. */
|
|
713
|
-
method: string;
|
|
714
|
-
/** Argument index carrying the subject. */
|
|
715
|
-
subjectArg: number;
|
|
716
|
-
/**
|
|
717
|
-
* Which argument the message body is. Left out when the method has no
|
|
718
|
-
* single body argument, as a batch method taking a list of entries
|
|
719
|
-
* does, and then no body is reported.
|
|
720
|
-
*/
|
|
721
|
-
bodyArg?: number;
|
|
722
|
-
}
|
|
1008
|
+
type ConfiguredCallSpec = z.infer<typeof configuredCallOption>;
|
|
723
1009
|
interface ConfiguredCallRead {
|
|
724
1010
|
/** The subject the call sends to, always a literal string. */
|
|
725
1011
|
subject: string;
|
|
@@ -763,7 +1049,7 @@ interface ContractReadResult {
|
|
|
763
1049
|
* Returns null if the handler wasn't registered with a contract or the contract
|
|
764
1050
|
* can't be resolved.
|
|
765
1051
|
*/
|
|
766
|
-
declare function readContract(unit: DiscoveredUnit, pattern: ContractPattern, framework: string): ContractReadResult | null;
|
|
1052
|
+
declare function readContract(unit: DiscoveredUnit, pattern: ContractPattern, framework: string, resolution?: ResolutionStore): ContractReadResult | null;
|
|
767
1053
|
/**
|
|
768
1054
|
* Resolve the contract for a consumer call site.
|
|
769
1055
|
*
|
|
@@ -771,7 +1057,90 @@ declare function readContract(unit: DiscoveredUnit, pattern: ContractPattern, fr
|
|
|
771
1057
|
* call to find the contract, then extracts the endpoint definition for the
|
|
772
1058
|
* matched method name (e.g. "getUser").
|
|
773
1059
|
*/
|
|
774
|
-
declare function readContractForClientCall(callExpression: Node, methodName: string, pattern: ContractPattern, framework: string): ContractReadResult | null;
|
|
1060
|
+
declare function readContractForClientCall(callExpression: Node, methodName: string, pattern: ContractPattern, framework: string, resolution?: ResolutionStore): ContractReadResult | null;
|
|
1061
|
+
|
|
1062
|
+
/**
|
|
1063
|
+
* helperIndex.ts: reading the project's own helpers once, before any
|
|
1064
|
+
* file is walked.
|
|
1065
|
+
*
|
|
1066
|
+
* A pack that declares `projectHelpers` gets every helper the project
|
|
1067
|
+
* wrote in front of its library, each read in terms of its own
|
|
1068
|
+
* parameters, and gives back the patterns and recognizers it would
|
|
1069
|
+
* otherwise have taken as config. Those join the pack for the rest of
|
|
1070
|
+
* the run, so the match happens at the call site, where the arguments
|
|
1071
|
+
* are literal.
|
|
1072
|
+
*
|
|
1073
|
+
* Built alongside the mount and wrapper indexes, over the same files.
|
|
1074
|
+
* The discovery README has the ordering and the cost.
|
|
1075
|
+
*/
|
|
1076
|
+
|
|
1077
|
+
interface ProjectHelperIndex {
|
|
1078
|
+
/** Discovery patterns `packName` contributed after reading the project. */
|
|
1079
|
+
patternsFor(packName: string): readonly DiscoveryPattern[];
|
|
1080
|
+
/**
|
|
1081
|
+
* Recognizers the packs contributed. They match calls to functions
|
|
1082
|
+
* this project declares, so they run wherever a call can appear
|
|
1083
|
+
* rather than only where the pack's own import gate reaches.
|
|
1084
|
+
*/
|
|
1085
|
+
contributedRecognizers(): readonly InvocationRecognizer[];
|
|
1086
|
+
/**
|
|
1087
|
+
* The helper files that shaped what `file` extracts to, so the
|
|
1088
|
+
* per-file cache invalidates `file` when one of them is edited.
|
|
1089
|
+
*/
|
|
1090
|
+
helperFilesFor(file: SourceFile): readonly string[];
|
|
1091
|
+
/**
|
|
1092
|
+
* Whether a registration written inside `helper` with `method` is one
|
|
1093
|
+
* the call sites already expand. Reading it here as well would give
|
|
1094
|
+
* one registration two summaries, and which of the two a run kept
|
|
1095
|
+
* would come down to the order the files were walked in.
|
|
1096
|
+
*/
|
|
1097
|
+
expandedAtCallSites(helper: Node, method: string): boolean;
|
|
1098
|
+
}
|
|
1099
|
+
declare function buildProjectHelperIndex(sourceFiles: ReadonlyArray<SourceFile>, packs: ReadonlyArray<PatternPack>, packsByFile: ReadonlyMap<SourceFile, readonly PatternPack[]>, resolution: ResolutionStore): ProjectHelperIndex;
|
|
1100
|
+
|
|
1101
|
+
/**
|
|
1102
|
+
* The one import scan.
|
|
1103
|
+
*
|
|
1104
|
+
* Fifteen copies of "which names did this file import from module X"
|
|
1105
|
+
* grew across discovery handlers and packs, and two of them disagreed
|
|
1106
|
+
* about aliases (#674). Every question about a file's imports of a
|
|
1107
|
+
* module is asked here: which declarations name it, what the named
|
|
1108
|
+
* imports are called locally, and which local spellings the default
|
|
1109
|
+
* and namespace imports go by. Matching semantics are explicit
|
|
1110
|
+
* options, so a caller that accepts subpath specifiers or resolves
|
|
1111
|
+
* path-shaped specifiers through the store says so, and one that
|
|
1112
|
+
* matches the specifier verbatim stays verbatim.
|
|
1113
|
+
*/
|
|
1114
|
+
|
|
1115
|
+
interface ImportScanOptions {
|
|
1116
|
+
/**
|
|
1117
|
+
* Accept `module/subpath` specifiers beside the exact module, the
|
|
1118
|
+
* way `react-dom/client` is still react-dom's surface.
|
|
1119
|
+
*/
|
|
1120
|
+
subpaths?: boolean;
|
|
1121
|
+
/** Resolve path-shaped specifiers through the store's module graph. */
|
|
1122
|
+
resolution?: ResolutionStore;
|
|
1123
|
+
}
|
|
1124
|
+
/** One named import: how the file spells it, and what it is. */
|
|
1125
|
+
interface NamedImport {
|
|
1126
|
+
/** The spelling this file binds, the alias when there is one. */
|
|
1127
|
+
local: string;
|
|
1128
|
+
/** The name the module exports it as. */
|
|
1129
|
+
canonical: string;
|
|
1130
|
+
/** The specifier as written, for a caller that reads sub-paths. */
|
|
1131
|
+
specifier: string;
|
|
1132
|
+
}
|
|
1133
|
+
/** Every named import of these modules, aliases resolved. */
|
|
1134
|
+
declare function namedImportsOf(sourceFile: SourceFile, modules: readonly string[], options?: ImportScanOptions): NamedImport[];
|
|
1135
|
+
/**
|
|
1136
|
+
* Local spelling to canonical exported name, for every named import
|
|
1137
|
+
* of these modules. `import { Get as HttpGet }` yields HttpGet -> Get.
|
|
1138
|
+
*/
|
|
1139
|
+
declare function importedNamesOf(sourceFile: SourceFile, modules: readonly string[], options?: ImportScanOptions): Map<string, string>;
|
|
1140
|
+
/** The local spellings of default and namespace imports of these modules. */
|
|
1141
|
+
declare function importedRootsOf(sourceFile: SourceFile, modules: readonly string[], options?: ImportScanOptions): Set<string>;
|
|
1142
|
+
/** Every import declaration in the file that names one of `modules`. */
|
|
1143
|
+
declare function importDeclarationsOf(sourceFile: SourceFile, modules: readonly string[], options?: ImportScanOptions): ImportDeclaration[];
|
|
775
1144
|
|
|
776
1145
|
interface TsDiscoveryContext {
|
|
777
1146
|
/** Full filesystem path of the source file. Useful for excluding
|
|
@@ -794,32 +1163,6 @@ interface TsDiscoveryContext {
|
|
|
794
1163
|
func: FunctionRoot;
|
|
795
1164
|
isDefault: boolean;
|
|
796
1165
|
}>;
|
|
797
|
-
/**
|
|
798
|
-
* For an export the project builds by calling a factory, the string
|
|
799
|
-
* under a property of that call's config object:
|
|
800
|
-
* `export const handler = makeWidgetHandler({ subject: "a.b" }, ...)`
|
|
801
|
-
* with `{ property: "subject" }` gives back `"a.b"`.
|
|
802
|
-
*
|
|
803
|
-
* The caller does not have to say which function was called or which
|
|
804
|
-
* argument the config was in. Every object argument is read. Giving the
|
|
805
|
-
* callee or fixing the argument position narrows that down, for a
|
|
806
|
-
* project whose factories would otherwise collide.
|
|
807
|
-
*
|
|
808
|
-
* Two arguments with the property set to different values give back
|
|
809
|
-
* null, since nothing says which one was meant.
|
|
810
|
-
*
|
|
811
|
-
* The config argument is usually an object literal at the call site;
|
|
812
|
-
* a variable or import is followed to the literal it resolves to.
|
|
813
|
-
* `as const` and parentheses around the property value are peeled.
|
|
814
|
-
* Anything but a string literal underneath (a computed subject, a
|
|
815
|
-
* template, a call) gives back null, and the caller attaches nothing
|
|
816
|
-
* rather than guessing.
|
|
817
|
-
*/
|
|
818
|
-
exportedCallConfigString(sourceFile: SourceFile, exportName: string, spec: {
|
|
819
|
-
callees?: string[];
|
|
820
|
-
argIndex?: number;
|
|
821
|
-
property: string;
|
|
822
|
-
}): string | null;
|
|
823
1166
|
/**
|
|
824
1167
|
* Walk a function's body for return statements whose value is a
|
|
825
1168
|
* JSX element / fragment / self-closing tag. Returns true on the
|
|
@@ -899,14 +1242,11 @@ declare class WhySession {
|
|
|
899
1242
|
private displayPath;
|
|
900
1243
|
}
|
|
901
1244
|
|
|
902
|
-
type ExportedDeclarationMap = ReturnType<SourceFile["getExportedDeclarations"]>;
|
|
903
1245
|
/**
|
|
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.
|
|
1246
|
+
* What a module exports, by exported name. The store's rules flatten
|
|
1247
|
+
* re-export chains of any length, and the store memoizes per file.
|
|
908
1248
|
*/
|
|
909
|
-
declare function exportedDeclarationsOf(sourceFile: SourceFile):
|
|
1249
|
+
declare function exportedDeclarationsOf(sourceFile: SourceFile, resolution: ResolutionStore): Map<string, Node[]>;
|
|
910
1250
|
/**
|
|
911
1251
|
* `Symbol.getAliasedSymbol`, with the re-export chains warmed first so
|
|
912
1252
|
* that an import sitting at the top of a deep chain still resolves
|
|
@@ -1031,117 +1371,31 @@ type Called = CallExpression | NewExpression | TaggedTemplateExpression;
|
|
|
1031
1371
|
/** One-hop lookup from a written name to the value it was bound to. */
|
|
1032
1372
|
type Resolve = (value: Node) => Node | null;
|
|
1033
1373
|
/** What a declared pack can ask about one TypeScript call. */
|
|
1034
|
-
declare function callOpsFor(call: Called, resolveWrittenValue?: Resolve): AstCapableOps;
|
|
1374
|
+
declare function callOpsFor(call: Called, resolveWrittenValue?: Resolve, originatesFrom?: OriginatesFrom, anchorCallsOf?: AnchorCallsOf): AstCapableOps;
|
|
1035
1375
|
|
|
1036
1376
|
/**
|
|
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.
|
|
1377
|
+
* The one resolver from a reference to the function behind it.
|
|
1115
1378
|
*
|
|
1116
|
-
*
|
|
1117
|
-
*
|
|
1379
|
+
* Four copies of "follow an identifier to its function declaration"
|
|
1380
|
+
* grew across the closure, the render-tree builder, the react pack,
|
|
1381
|
+
* and the parameter-read walk, three of them lossy (#674). The walk
|
|
1382
|
+
* lives here: alias-following through imports, shorthand properties
|
|
1383
|
+
* resolved to the binding they read, overload signatures routed to
|
|
1384
|
+
* the declaration with the body, and external code refused. Callers
|
|
1385
|
+
* that need only the file and name take `functionTargetOf`; the
|
|
1386
|
+
* closure takes `resolveDecl` for the function root itself.
|
|
1118
1387
|
*/
|
|
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;
|
|
1388
|
+
|
|
1136
1389
|
/**
|
|
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.
|
|
1390
|
+
* The function an identifier refers to, as its declaration's file and
|
|
1391
|
+
* name, for joins that never walk the body. Null when the reference
|
|
1392
|
+
* does not land on a project function.
|
|
1143
1393
|
*/
|
|
1144
|
-
declare function
|
|
1394
|
+
declare function functionTargetOf(node: Identifier): {
|
|
1395
|
+
func: FunctionRoot;
|
|
1396
|
+
file: string;
|
|
1397
|
+
name: string;
|
|
1398
|
+
} | null;
|
|
1145
1399
|
|
|
1146
1400
|
/**
|
|
1147
1401
|
* What a name-valued expression says, as fixed text with a hole for
|
|
@@ -1192,6 +1446,33 @@ declare function collectClientFieldAccesses(callExpr: CallExpression, func: Node
|
|
|
1192
1446
|
end: number;
|
|
1193
1447
|
}>, responseSemantics?: ResponsePropertyMapping[]): BranchFieldAccesses[];
|
|
1194
1448
|
|
|
1449
|
+
/**
|
|
1450
|
+
* Evidence for drafting a dependency stub: every call the project
|
|
1451
|
+
* makes into a named package, grouped by the export it reaches, with
|
|
1452
|
+
* the argument shapes observed at each call site. `suss infer stub`
|
|
1453
|
+
* turns this into a stub skeleton for an author to fill in. The
|
|
1454
|
+
* package's own code is never read, only the project's calls into it,
|
|
1455
|
+
* so this works for packages whose source no adapter can parse.
|
|
1456
|
+
*/
|
|
1457
|
+
|
|
1458
|
+
interface ObservedStubCall {
|
|
1459
|
+
readonly file: string;
|
|
1460
|
+
readonly line: number;
|
|
1461
|
+
readonly args: EffectArg[];
|
|
1462
|
+
}
|
|
1463
|
+
interface StubCallEvidence {
|
|
1464
|
+
readonly exportPath: string[];
|
|
1465
|
+
readonly calls: ObservedStubCall[];
|
|
1466
|
+
}
|
|
1467
|
+
declare function stubEvidenceIn(project: Project, packageName: string, root: string): StubCallEvidence[];
|
|
1468
|
+
interface StubEvidenceOptions {
|
|
1469
|
+
packageName: string;
|
|
1470
|
+
tsConfigFilePath?: string;
|
|
1471
|
+
/** Read when no tsconfig is given. */
|
|
1472
|
+
directory?: string;
|
|
1473
|
+
}
|
|
1474
|
+
declare function stubEvidence(options: StubEvidenceOptions): StubCallEvidence[];
|
|
1475
|
+
|
|
1195
1476
|
/**
|
|
1196
1477
|
* Resolve a ts-morph Expression node to a structured ValueRef.
|
|
1197
1478
|
* Uses only expr.getSymbol()?.getDeclarations()[0] for symbol lookup ,
|
|
@@ -1330,4 +1611,4 @@ declare function computeAdapterPacksDigest(packVersions: ReadonlyArray<{
|
|
|
1330
1611
|
version?: string;
|
|
1331
1612
|
}>): string;
|
|
1332
1613
|
|
|
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 };
|
|
1614
|
+
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, buildProjectHelperIndex, 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 };
|