carrick 0.3.105 → 0.3.107
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/hook/refresh.js +8 -1
- package/dist/hook/refresh.js.map +1 -1
- package/package.json +6 -6
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/sidecar/dist/src/capture/anchors.d.ts +22 -2
- package/sidecar/dist/src/capture/anchors.js +178 -34
- package/sidecar/dist/src/capture/api.d.ts +42 -1
- package/sidecar/dist/src/capture/check-classify.d.ts +9 -1
- package/sidecar/dist/src/capture/check-classify.js +15 -0
- package/sidecar/dist/src/capture/check-poison.js +4 -14
- package/sidecar/dist/src/capture/check.js +13 -1
- package/sidecar/dist/src/capture/index.js +55 -29
- package/sidecar/dist/src/capture/installed-package.d.ts +2 -0
- package/sidecar/dist/src/capture/installed-package.js +2 -1
- package/sidecar/dist/src/capture/outside-root.d.ts +19 -0
- package/sidecar/dist/src/capture/outside-root.js +39 -2
- package/sidecar/dist/src/capture/self-check.js +12 -13
- package/sidecar/dist/src/capture/service-config.d.ts +2 -0
- package/sidecar/dist/src/capture/service-config.js +1 -1
- package/sidecar/dist/src/capture/specifiers.d.ts +14 -0
- package/sidecar/dist/src/capture/specifiers.js +25 -0
- package/sidecar/dist/src/failure-path.d.ts +34 -3
- package/sidecar/dist/src/failure-path.js +59 -35
- package/sidecar/dist/src/function-line-index.d.ts +30 -0
- package/sidecar/dist/src/function-line-index.js +162 -0
- package/sidecar/dist/src/index.d.ts +5 -0
- package/sidecar/dist/src/index.js +29 -5
- package/sidecar/dist/src/line-index.d.ts +9 -0
- package/sidecar/dist/src/line-index.js +26 -0
- package/sidecar/dist/src/printed-names.d.ts +43 -0
- package/sidecar/dist/src/printed-names.js +186 -0
- package/sidecar/dist/src/progress.d.ts +22 -0
- package/sidecar/dist/src/progress.js +31 -0
- package/sidecar/dist/src/retype.js +58 -128
- package/sidecar/dist/src/type-inferrer.d.ts +124 -13
- package/sidecar/dist/src/type-inferrer.js +531 -146
- package/sidecar/dist/src/type-structural-expander.js +10 -1
- package/sidecar/dist/src/types.d.ts +37 -6
- package/sidecar/dist/src/validators.d.ts +76 -0
- package/sidecar/dist/src/validators.js +8 -0
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
* project other requests read is the project the scan loaded.
|
|
26
26
|
*/
|
|
27
27
|
import { Node, SyntaxKind, ts } from 'ts-morph';
|
|
28
|
+
import { readsResponseStatus, statusesIn, SUCCEEDED, testsOnPath, } from './failure-path.js';
|
|
29
|
+
import { lineIndex } from './line-index.js';
|
|
28
30
|
import { fileDiagnostics } from './unwidened.js';
|
|
29
31
|
/** Names appended to a file that is not ours carry this prefix. */
|
|
30
32
|
const PREFIX = '__carrick_';
|
|
@@ -688,124 +690,71 @@ function responseTest(read) {
|
|
|
688
690
|
return (node) => Node.isIdentifier(node) && node.getSymbol() === symbol;
|
|
689
691
|
}
|
|
690
692
|
/**
|
|
691
|
-
*
|
|
692
|
-
*
|
|
693
|
-
*
|
|
693
|
+
* Whether `node` sits on the response's error path (`'failure'`), on a path
|
|
694
|
+
* whose status tests do not say (`'unclear'`), or where the producer's body
|
|
695
|
+
* is read (`undefined`, also when no test of the response is on its path).
|
|
696
|
+
*
|
|
697
|
+
* The tests on the path are read as failure-path.ts reads them, each as the
|
|
698
|
+
* statuses that take the side `node` is on, and taken together. On top of
|
|
699
|
+
* that reading, in this order:
|
|
700
|
+
*
|
|
701
|
+
* - no success status reaches `node`: the error path;
|
|
702
|
+
* - a test lets through every status but one success status that carries a
|
|
703
|
+
* body (the side of `res.status === 200` the read after an early return on
|
|
704
|
+
* it is on): the error path. This is the consumer's own reading of that
|
|
705
|
+
* test, kept even when only success statuses get that far, because the
|
|
706
|
+
* read there is not the body the source singled out;
|
|
707
|
+
* - no status from 400 up reaches `node`: the producer's body;
|
|
708
|
+
* - a `switch` on the status, or a test the reading cannot follow exactly
|
|
709
|
+
* (`res.status === OK`, `res.ok || retry`), is on the path: unclear;
|
|
710
|
+
* - the tests take away a success status that carries a body
|
|
711
|
+
* (`res.status === 200 || res.status === 404`, `res.status > 200`):
|
|
712
|
+
* unclear;
|
|
713
|
+
* - otherwise they took away only error statuses, or statuses that carry no
|
|
714
|
+
* content (carrick#1813: the retype only runs against a producer that
|
|
715
|
+
* publishes a body, and that body never arrives with a 204 or 205), and
|
|
716
|
+
* `node` is where the body is read, as it is with no test at all.
|
|
694
717
|
*/
|
|
695
718
|
function sideOf(node, isResponse) {
|
|
696
|
-
|
|
697
|
-
const
|
|
698
|
-
if (
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
};
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
note(branchSide(statement.getExpression(), false, isResponse));
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
return found;
|
|
719
|
+
const sides = testsOnPath(node, undefined, isResponse);
|
|
720
|
+
const switched = node.getAncestors().some((ancestor) => {
|
|
721
|
+
if (!Node.isCaseClause(ancestor) && !Node.isDefaultClause(ancestor))
|
|
722
|
+
return false;
|
|
723
|
+
const statement = ancestor.getParent()?.getParent();
|
|
724
|
+
return (!!statement &&
|
|
725
|
+
Node.isSwitchStatement(statement) &&
|
|
726
|
+
readsResponseStatus(statement.getExpression(), isResponse));
|
|
727
|
+
});
|
|
728
|
+
if (sides.length === 0 && !switched)
|
|
729
|
+
return undefined;
|
|
730
|
+
const admitted = (status) => sides.every((side) => side.admits(status));
|
|
731
|
+
const reaching = statusesIn(admitted);
|
|
732
|
+
if (!reaching.some(SUCCEEDED))
|
|
733
|
+
return 'failure';
|
|
734
|
+
if (sides.some((side) => singlesOutABody(side.admits)))
|
|
735
|
+
return 'failure';
|
|
736
|
+
if (!reaching.some((status) => status >= 400))
|
|
737
|
+
return undefined;
|
|
738
|
+
if (switched || sides.some((side) => side.inexact))
|
|
739
|
+
return 'unclear';
|
|
740
|
+
if (statusesIn((status) => !admitted(status)).some(carriesBody))
|
|
741
|
+
return 'unclear';
|
|
742
|
+
return undefined;
|
|
743
|
+
}
|
|
744
|
+
/** `statuses` is every status but one success status that carries a body. */
|
|
745
|
+
function singlesOutABody(statuses) {
|
|
746
|
+
const excluded = statusesIn((status) => !statuses(status));
|
|
747
|
+
return excluded.length === 1 && carriesBody(excluded[0]);
|
|
731
748
|
}
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
return ok;
|
|
736
|
-
return ok === whenTrue ? 'success' : 'failure';
|
|
749
|
+
/** A success status whose response can carry the producer's body. */
|
|
750
|
+
function carriesBody(status) {
|
|
751
|
+
return SUCCEEDED(status) && !NO_CONTENT_STATUSES.has(status);
|
|
737
752
|
}
|
|
738
753
|
/**
|
|
739
754
|
* The success statuses whose response carries no content (RFC 9110: 204 No
|
|
740
755
|
* Content, 205 Reset Content).
|
|
741
756
|
*/
|
|
742
757
|
const NO_CONTENT_STATUSES = new Set([204, 205]);
|
|
743
|
-
/**
|
|
744
|
-
* Whether `condition` being true means the response succeeded: `res.ok`,
|
|
745
|
-
* `res.status === 200`, `res.status !== 200`, `res.status >= 400` and their
|
|
746
|
-
* negations. Any other test of the response is `'unclear'`; a condition that does not
|
|
747
|
-
* test the response is `undefined`.
|
|
748
|
-
*
|
|
749
|
-
* An equality or inequality with a no-content status is `undefined` too
|
|
750
|
-
* (carrick#1813). The retype only runs against a producer that publishes a
|
|
751
|
-
* response body, and that body never arrives with a 204 or 205, so
|
|
752
|
-
* `if (res.status === 204) return null` only takes away a status the body
|
|
753
|
-
* cannot come with. The read after it sits where a read no test decides
|
|
754
|
-
* sits, not on the error path.
|
|
755
|
-
*/
|
|
756
|
-
function okWhenTrue(condition, isResponse) {
|
|
757
|
-
let e = condition;
|
|
758
|
-
while (Node.isParenthesizedExpression(e))
|
|
759
|
-
e = e.getExpression();
|
|
760
|
-
if (Node.isPrefixUnaryExpression(e) && e.getOperatorToken() === SyntaxKind.ExclamationToken) {
|
|
761
|
-
const inner = okWhenTrue(e.getOperand(), isResponse);
|
|
762
|
-
return typeof inner === 'boolean' ? !inner : inner;
|
|
763
|
-
}
|
|
764
|
-
if (isMember(e, 'ok', isResponse))
|
|
765
|
-
return true;
|
|
766
|
-
if (Node.isBinaryExpression(e)) {
|
|
767
|
-
const op = e.getOperatorToken().getKind();
|
|
768
|
-
const [left, right] = [e.getLeft(), e.getRight()];
|
|
769
|
-
const value = isMember(left, 'status', isResponse) && Node.isNumericLiteral(right)
|
|
770
|
-
? right.getLiteralValue()
|
|
771
|
-
: undefined;
|
|
772
|
-
if (value !== undefined) {
|
|
773
|
-
const success = value >= 200 && value < 300;
|
|
774
|
-
const noContent = NO_CONTENT_STATUSES.has(value);
|
|
775
|
-
switch (op) {
|
|
776
|
-
case SyntaxKind.EqualsEqualsEqualsToken:
|
|
777
|
-
case SyntaxKind.EqualsEqualsToken:
|
|
778
|
-
return noContent ? undefined : success;
|
|
779
|
-
case SyntaxKind.ExclamationEqualsEqualsToken:
|
|
780
|
-
case SyntaxKind.ExclamationEqualsToken:
|
|
781
|
-
return noContent ? undefined : !success;
|
|
782
|
-
case SyntaxKind.GreaterThanEqualsToken:
|
|
783
|
-
if (value >= 300)
|
|
784
|
-
return false;
|
|
785
|
-
break;
|
|
786
|
-
}
|
|
787
|
-
return 'unclear';
|
|
788
|
-
}
|
|
789
|
-
}
|
|
790
|
-
return testsResponse(e, isResponse) ? 'unclear' : undefined;
|
|
791
|
-
}
|
|
792
|
-
function isMember(node, name, isResponse) {
|
|
793
|
-
return (Node.isPropertyAccessExpression(node) && node.getName() === name && isResponse(node.getExpression()));
|
|
794
|
-
}
|
|
795
|
-
/** The expression reads the response's `ok` or `status`. */
|
|
796
|
-
function testsResponse(node, isResponse) {
|
|
797
|
-
return [node, ...node.getDescendantsOfKind(SyntaxKind.PropertyAccessExpression)].some((n) => isMember(n, 'ok', isResponse) || isMember(n, 'status', isResponse));
|
|
798
|
-
}
|
|
799
|
-
/** A statement that always leaves the function. */
|
|
800
|
-
function exits(statement) {
|
|
801
|
-
if (Node.isReturnStatement(statement) || Node.isThrowStatement(statement))
|
|
802
|
-
return true;
|
|
803
|
-
if (Node.isBlock(statement)) {
|
|
804
|
-
const last = statement.getStatements().at(-1);
|
|
805
|
-
return !!last && exits(last);
|
|
806
|
-
}
|
|
807
|
-
return false;
|
|
808
|
-
}
|
|
809
758
|
/** `node.json()` with no arguments, where `node` is the receiver. */
|
|
810
759
|
function bodyReadOn(node) {
|
|
811
760
|
const access = node.getParent();
|
|
@@ -894,22 +843,3 @@ function mapBack(pos, edits) {
|
|
|
894
843
|
}
|
|
895
844
|
return { kind: 'original', pos: pos - shift };
|
|
896
845
|
}
|
|
897
|
-
/** 1-based line of an original-file position. */
|
|
898
|
-
function lineIndex(text) {
|
|
899
|
-
const starts = [0];
|
|
900
|
-
for (let i = 0; i < text.length; i++)
|
|
901
|
-
if (text[i] === '\n')
|
|
902
|
-
starts.push(i + 1);
|
|
903
|
-
return (pos) => {
|
|
904
|
-
let lo = 0;
|
|
905
|
-
let hi = starts.length - 1;
|
|
906
|
-
while (lo < hi) {
|
|
907
|
-
const mid = (lo + hi + 1) >> 1;
|
|
908
|
-
if (starts[mid] <= pos)
|
|
909
|
-
lo = mid;
|
|
910
|
-
else
|
|
911
|
-
hi = mid - 1;
|
|
912
|
-
}
|
|
913
|
-
return lo + 1;
|
|
914
|
-
};
|
|
915
|
-
}
|
|
@@ -63,6 +63,11 @@ export interface TypeInferrerOptions {
|
|
|
63
63
|
*/
|
|
64
64
|
unwidenedBudgetMs?: number;
|
|
65
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Called each time an `infer` batch is done with one of its requests,
|
|
68
|
+
* whatever that request answered: skipped, refused, failed or inferred.
|
|
69
|
+
*/
|
|
70
|
+
export type InferRequestDone = () => void;
|
|
66
71
|
/**
|
|
67
72
|
* TypeInferrer - Extracts types from source code, both explicit and inferred
|
|
68
73
|
*
|
|
@@ -94,9 +99,15 @@ export declare class TypeInferrer {
|
|
|
94
99
|
*
|
|
95
100
|
* @param requests - Array of inference requests
|
|
96
101
|
* @param extractionConfig - Agent-generated extraction config for payload unwrapping
|
|
102
|
+
* @param onRequestDone - Called once per request, as the batch is done with it
|
|
97
103
|
* @returns InferResult with inferred types or errors
|
|
98
104
|
*/
|
|
99
|
-
infer(requests: InferRequestItem[], extractionConfig?: ExtractionConfig): InferResult;
|
|
105
|
+
infer(requests: InferRequestItem[], extractionConfig?: ExtractionConfig, onRequestDone?: InferRequestDone): InferResult;
|
|
106
|
+
/**
|
|
107
|
+
* carrick#1836: list on `result` the declarations behind the names its text
|
|
108
|
+
* prints that the request's file cannot resolve (`PrintedTypes.namesIn`).
|
|
109
|
+
*/
|
|
110
|
+
private recordPrintedNames;
|
|
100
111
|
/**
|
|
101
112
|
* carrick#1516: read each response inference again with the literals on its
|
|
102
113
|
* handler's path marked `as const`, and record the narrower type the handler
|
|
@@ -257,6 +268,25 @@ export declare class TypeInferrer {
|
|
|
257
268
|
*/
|
|
258
269
|
private receivingCallOf;
|
|
259
270
|
private inferCallResult;
|
|
271
|
+
/**
|
|
272
|
+
* The terminal of a call's def-use walk is a zero-argument `.text()` read of
|
|
273
|
+
* the call's own result (carrick#1842): on its binding (`res.text()`,
|
|
274
|
+
* through a declaration, `await` or a cast), or in the callback a `then` on
|
|
275
|
+
* the call hands the response to (`fetch(u).then((res) => res.text())`).
|
|
276
|
+
*/
|
|
277
|
+
private textReadAtTerminal;
|
|
278
|
+
/** `call` is `<receiver>.text()` with no arguments, and `accept` takes its receiver. */
|
|
279
|
+
private isTextReadOf;
|
|
280
|
+
/**
|
|
281
|
+
* The call's resolved signature, at this site, types a member of an object
|
|
282
|
+
* argument as exactly the literal `'text'`, and the source passes that
|
|
283
|
+
* literal there (carrick#1842). That is how a request library lets a caller
|
|
284
|
+
* choose a text body from the formats it offers (`{ type: 'text' }`): a
|
|
285
|
+
* generic config instantiated by the literal, or an overload taken by it.
|
|
286
|
+
* A member typed as a wider union (`kind: 'text' | 'image'`) chooses no
|
|
287
|
+
* format, and no member name is read.
|
|
288
|
+
*/
|
|
289
|
+
private callChoosesTextBody;
|
|
260
290
|
/**
|
|
261
291
|
* What the source states the body read at `terminal` to be, when the type
|
|
262
292
|
* `extractExplicitTypeFromAncestor` printed for it is stated AT the read
|
|
@@ -326,12 +356,54 @@ export declare class TypeInferrer {
|
|
|
326
356
|
*/
|
|
327
357
|
private resultCarrierPayload;
|
|
328
358
|
/**
|
|
329
|
-
*
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
|
|
359
|
+
* The shape test of `resultCarrierPayload`: the carrier `type` is, once a
|
|
360
|
+
* promise-like around it is peeled, and the type arguments a branch of it
|
|
361
|
+
* holds as a member. `undefined` when `type` is not a carrier.
|
|
362
|
+
*/
|
|
363
|
+
private resultCarrierArguments;
|
|
364
|
+
/**
|
|
365
|
+
* The decided abstain of a call whose result carries transport the
|
|
366
|
+
* service's wrapper rules verify and read no payload out of (carrick#1841,
|
|
367
|
+
* carrick#1843): `unknown` with `machinery_envelope` at the root and no
|
|
368
|
+
* anchor. The root reason is what keeps the capture's own locator from
|
|
369
|
+
* re-reading the raw call (`inference_decided_no_contract`,
|
|
370
|
+
* engine/type_compat_v2.rs).
|
|
371
|
+
*/
|
|
372
|
+
private transportAbstain;
|
|
373
|
+
/**
|
|
374
|
+
* `Future<T>` -> `T` for a thenable, read off the await protocol rather
|
|
375
|
+
* than a name: a `then` whose first parameter is a callback, whose own
|
|
376
|
+
* first parameter is the value awaiting it yields. `Promise` and
|
|
377
|
+
* `PromiseLike` are peeled by `unwrapPromiseType` before this.
|
|
378
|
+
*
|
|
379
|
+
* The callback is read through `null` and `undefined` (carrick#1877). A
|
|
380
|
+
* `then` of the source's own making declares `(value: T) => void`; the
|
|
381
|
+
* platform's declares `onfulfilled?: ((value: T) => ...) | null`, and that
|
|
382
|
+
* is the `then` a subclass of `Promise` inherits. Read as written, an
|
|
383
|
+
* optional, nullable callback has no call signature, and the subclass was
|
|
384
|
+
* not seen as a thenable at all.
|
|
385
|
+
*
|
|
386
|
+
* A `then` that cannot be called, or whose first parameter is no callback,
|
|
387
|
+
* is no protocol, and the type is returned as it is.
|
|
388
|
+
*
|
|
389
|
+
* The compiler's own awaited type arbitrates. This walk reads the first
|
|
390
|
+
* signature of `then`; the language reads all of them. Where awaiting the
|
|
391
|
+
* type and awaiting what this walk found are not the same thing to the
|
|
392
|
+
* compiler (an overloaded `then` whose first signature is not the one
|
|
393
|
+
* `await` takes), the walk did not read the protocol, and the type is
|
|
394
|
+
* returned as it is rather than published as a guess.
|
|
333
395
|
*/
|
|
334
396
|
private unwrapThenableType;
|
|
397
|
+
/** The value `then`'s first signature hands its callback, read until it stops changing. */
|
|
398
|
+
private firstThenValue;
|
|
399
|
+
/**
|
|
400
|
+
* What `await` yields for `type` where the names do not say: `type` is,
|
|
401
|
+
* once `Promise` and `PromiseLike` are peeled, a thenable by the protocol
|
|
402
|
+
* (a subclass of `Promise`, a class with a `then` of its own). `undefined`
|
|
403
|
+
* where the names say it all or `type` is no thenable, so a caller keeps
|
|
404
|
+
* the reading it had (carrick#1877).
|
|
405
|
+
*/
|
|
406
|
+
private awaitedBeyondPromise;
|
|
335
407
|
/**
|
|
336
408
|
* The platform's error shape, in full: `name` and `message` strings AND a
|
|
337
409
|
* `stack`, which is what the `Error` interface declares and every subclass
|
|
@@ -349,10 +421,10 @@ export declare class TypeInferrer {
|
|
|
349
421
|
* `query.data`, `envelope` in `envelope.list[0]` — or `undefined` when the
|
|
350
422
|
* identifier names the value itself.
|
|
351
423
|
*
|
|
352
|
-
* A member CALL is not a projection: `res.
|
|
424
|
+
* A member CALL is not a projection: `res.blob()` yields a body rather than
|
|
353
425
|
* a part of one, and what it returns stays the walk's business. The
|
|
354
|
-
* zero-argument json body
|
|
355
|
-
* is asked.
|
|
426
|
+
* zero-argument json and text body reads have their own branch and are
|
|
427
|
+
* taken before this is asked.
|
|
356
428
|
*/
|
|
357
429
|
private projectionOnReceiver;
|
|
358
430
|
/**
|
|
@@ -431,6 +503,22 @@ export declare class TypeInferrer {
|
|
|
431
503
|
* about the body and is skipped.
|
|
432
504
|
*/
|
|
433
505
|
private castsOfUnreadParameter;
|
|
506
|
+
/**
|
|
507
|
+
* The zero-argument whole-body read taken in place on the value `callExpr`
|
|
508
|
+
* yields, or `undefined` (carrick#1851): `(await fetch(url)).text()`. The
|
|
509
|
+
* receiver is the call itself, through the wrappers that leave a value as
|
|
510
|
+
* it is (parentheses, `await`, `!`), so it is the same read
|
|
511
|
+
* `bodyReadOnReceiver` finds on a binding of that value. A call that is not
|
|
512
|
+
* awaited first is read the same way: a request that is a promise and reads
|
|
513
|
+
* its own body (`send(url).json()`) yields the body from that read too.
|
|
514
|
+
*/
|
|
515
|
+
private bodyReadOnCallValue;
|
|
516
|
+
/**
|
|
517
|
+
* The zero-argument whole-body read that takes `receiver` as its receiver,
|
|
518
|
+
* `res.json()` or `res.text()`, or `undefined`. A text read is a body read
|
|
519
|
+
* like a json one (carrick#1842): without it, `return res.text()` left the
|
|
520
|
+
* walk on the response binding and published the transport object.
|
|
521
|
+
*/
|
|
434
522
|
private bodyReadOnReceiver;
|
|
435
523
|
private collectDefUseNodes;
|
|
436
524
|
private expressionUsesNames;
|
|
@@ -488,12 +576,27 @@ export declare class TypeInferrer {
|
|
|
488
576
|
* Try to unwrap a type using a single ExtractionRule.
|
|
489
577
|
*/
|
|
490
578
|
private tryUnwrapWithRule;
|
|
579
|
+
/**
|
|
580
|
+
* The names `type` goes by, own symbol first (carrick#1843).
|
|
581
|
+
*
|
|
582
|
+
* `type Task<A> = __Task<A>` has the class's symbol and arguments, and the
|
|
583
|
+
* alias's beside them. `type Reply<T> = { ... }` has the anonymous `__type`
|
|
584
|
+
* with no arguments of its own. `type Outcome<A, E> = Done<A, E> |
|
|
585
|
+
* Failed<A, E>` has no symbol of its own at all. In each, the alias and its
|
|
586
|
+
* arguments are what a rule naming `Task`, `Reply` or `Outcome` describes.
|
|
587
|
+
*/
|
|
588
|
+
private wrapperReadings;
|
|
491
589
|
/**
|
|
492
590
|
* Extract the payload type from a matched wrapper. Returns null when the
|
|
493
591
|
* rule matched the wrapper but no payload is recoverable from generics or
|
|
494
592
|
* property paths — the caller decides what a payload-less match means
|
|
495
593
|
* (verified machinery collapses to `unknown` after every rule has run;
|
|
496
594
|
* a name-only match leaves the type untouched).
|
|
595
|
+
*
|
|
596
|
+
* `payloadGenericIndex` counts the arguments of `reading`, the name the
|
|
597
|
+
* rule matched (carrick#1843): an alias is free to order its parameters
|
|
598
|
+
* differently from the type it stands for, so the same index into the
|
|
599
|
+
* other list is a different argument.
|
|
497
600
|
*/
|
|
498
601
|
private extractPayloadFromWrapper;
|
|
499
602
|
/**
|
|
@@ -890,11 +993,19 @@ export declare class TypeInferrer {
|
|
|
890
993
|
/**
|
|
891
994
|
* Declaration file (absolute path) of the anchor symbol
|
|
892
995
|
* `primaryTypeSymbol` reports for this type, or `undefined` when the type
|
|
893
|
-
* has no user-facing anchor or no source declaration.
|
|
894
|
-
*
|
|
895
|
-
*
|
|
896
|
-
*
|
|
897
|
-
*
|
|
996
|
+
* has no user-facing anchor or no source declaration. Every path that
|
|
997
|
+
* reports the symbol reports this beside it (carrick#1819): it is where a
|
|
998
|
+
* reader finds the type an anchor names. The scanner's pub/sub two-anchor
|
|
999
|
+
* arbitration (carrick#413) also uses it to re-aim a demoted explicit
|
|
1000
|
+
* bundle request: the bundler resolves a `SymbolRequest` only against
|
|
1001
|
+
* declarations IN its `source_file`, so the request must point at the file
|
|
1002
|
+
* that actually declares the tsc-witnessed payload type.
|
|
1003
|
+
*
|
|
1004
|
+
* The declarations read are those of the type's own symbol, so a name
|
|
1005
|
+
* imported through a barrel reports the file that declares it, and a name
|
|
1006
|
+
* two files declare reports the one this type resolves to. A declaration in
|
|
1007
|
+
* an installed package or a TypeScript lib is reported as it is found, as
|
|
1008
|
+
* an absolute path; what a reader is shown for it is the scanner's call.
|
|
898
1009
|
*
|
|
899
1010
|
* Only declaration kinds the bundler's `validateSymbols` can resolve
|
|
900
1011
|
* (interface, type alias, class, enum, function, variable) count. A
|