carrick 0.3.125 → 0.3.126

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.
@@ -71,6 +71,17 @@ export declare const FLAG_TOO_MANY = 16;
71
71
  export declare const FLAG_PUBLISHED = 32;
72
72
  /** The declaration is what its module exports as `export =` or `default` (carrick#2508). */
73
73
  export declare const FLAG_MODULE_DEFAULT = 64;
74
+ /**
75
+ * A `call` row only: the call's declared return is the result of the
76
+ * function it is handed (`ReturnType<F>`, a bare type parameter the handed
77
+ * function returns, or an awaitable of one), so the library runs it and
78
+ * hands its result back (carrick#2634). Set when the call passes at least
79
+ * one argument at a function-typed parameter and every such parameter
80
+ * meets that return. The last free bit of the `u8`: the next flag widens
81
+ * the field and bumps the format. Pinned to `FLAG_RUNS_HANDED` in
82
+ * `src/position_rows.rs` by `position-rows-runs-handed.test.ts`.
83
+ */
84
+ export declare const FLAG_RUNS_HANDED = 128;
74
85
  /** The most `decl` rows one position lists. */
75
86
  export declare const DECL_CAP = 16;
76
87
  /** The kinds {@link kindOf} gives a node; `decl` and `jsx` rows are written beside them. */
@@ -109,14 +120,26 @@ export interface PositionRowsOptions {
109
120
  export declare function writePositionRows(options: PositionRowsOptions): PositionRowsCounts;
110
121
  /** What a declaration's file is written as in a row's `decl_file`: `lib:<name>` for the default library, else `PathNames`'. */
111
122
  export declare function declaringFileName(program: ts.Program, paths: PathNames, file: ts.SourceFile): string | null;
123
+ /** The installed package directory a resolved file lies in, and its name, as the module graph places it. */
124
+ export type PackageDirectoryOf = (fileName: string) => {
125
+ directory: string;
126
+ name: string;
127
+ } | undefined;
112
128
  /**
113
129
  * Names for the files rows point at, never an absolute path: relative to the
114
130
  * scanned repo's root when inside it (its real path too, so a root reached
115
131
  * through a link still contains its files), `lib:<name>` for the compiler's
116
132
  * default library, `pkg:<name>/<path>` for an installed package outside the
117
133
  * root, and nothing otherwise.
134
+ *
135
+ * An installed package outside the root is found by its path's last
136
+ * `node_modules` segment, else by `packageDirectoryOf`: the module graph's
137
+ * answer where the resolver serves a package from a cache whose path has no
138
+ * `node_modules` segment (carrick#2599). Either way the directory must hold a
139
+ * package.json.
118
140
  */
119
141
  export declare class PathNames {
142
+ private readonly packageDirectoryOf;
120
143
  private readonly roots;
121
144
  private readonly packageNames;
122
145
  /**
@@ -126,7 +149,7 @@ export declare class PathNames {
126
149
  */
127
150
  private readonly declaringFiles;
128
151
  private readonly declaringPackages;
129
- constructor(scanRoot: string);
152
+ constructor(scanRoot: string, packageDirectoryOf?: PackageDirectoryOf);
130
153
  /** The root `file` lies under, and its path from there; `undefined` outside every root. */
131
154
  private inside;
132
155
  /** A request file's name: relative to the root, which every file the scanner sends is inside. */
@@ -151,5 +174,100 @@ export declare class PathNames {
151
174
  */
152
175
  scrubType(text: string): string;
153
176
  }
177
+ /**
178
+ * The rows of one program's files. The `implementations` action
179
+ * (`implementations.ts`, carrick#2432) reads a call's symbol and names its
180
+ * answers through the same walker, so they join as the rows do.
181
+ */
182
+ export declare class PositionWalker {
183
+ private readonly program;
184
+ private readonly paths;
185
+ private readonly loader;
186
+ private readonly checker;
187
+ /** Each module's exports by name, and its `export =` and `default` targets, aliases followed. */
188
+ private readonly moduleExports;
189
+ constructor(program: ts.Program, paths: PathNames, loader: ProjectLoader);
190
+ rowsOf(sourceFile: ts.SourceFile): PositionRow[];
191
+ private row;
192
+ /**
193
+ * Whether a call's declared return is the result of the function it is
194
+ * handed (carrick#2634), read from the declared signature through public
195
+ * checker calls. See {@link FLAG_RUNS_HANDED}.
196
+ */
197
+ private runsHanded;
198
+ /** The call signatures of a parameter's type, a type parameter read through its constraint, `null` and `undefined` skipped. */
199
+ private callSignaturesOf;
200
+ /** The compiler's own awaited type differs from the type: `Promise<R>`, `PromiseLike<R>`. */
201
+ private isAwaitable;
202
+ /**
203
+ * An intrinsic element's type: the attributes `JSX.IntrinsicElements`
204
+ * gives its tag. The compiler types an intrinsic tag name itself as the
205
+ * error type, though the name resolves. A tag is intrinsic when it is an
206
+ * identifier that starts with a lowercase letter or holds a `-`, as the
207
+ * language reads it.
208
+ */
209
+ private intrinsicProps;
210
+ /** How rows name a position in a program file: its file, 1-based line and package. */
211
+ located(declaringFile: ts.SourceFile, position: number): {
212
+ declFile: string | null;
213
+ declLine: number;
214
+ declPackage: string | null;
215
+ };
216
+ /**
217
+ * The declaration a member with none is attributed to (carrick#2448): the
218
+ * mapped type node, or the alias naming it, of the receiver's type. A
219
+ * mapped type's members are made by the checker and have no declaration of
220
+ * their own. This is the owner `memberTypeWithoutDeclaration` reads such a
221
+ * member at (type-structural-expander.ts): the type's symbol, else its
222
+ * alias symbol. A union or intersection receiver contributes the one
223
+ * constituent that has the property; with several the row is left as it is.
224
+ */
225
+ private ownerDeclaration;
226
+ /** The declaration of a type's symbol, else of its alias symbol: a mapped type node, or the alias naming it. */
227
+ private typeDeclaration;
228
+ /**
229
+ * How `declaration`'s module publishes `symbol`: {@link FLAG_PUBLISHED}
230
+ * when under the symbol's own name (or as a global), and
231
+ * {@link FLAG_MODULE_DEFAULT} when as the module's `export =` or `default`.
232
+ * The module is the nearest ambient `declare module "…"` or the file.
233
+ */
234
+ private publication;
235
+ /** A namespace member, found among the exports of the module it sits in. */
236
+ private publishedByExports;
237
+ private publishedIn;
238
+ /** The type of the object a `member` or `call` row's name is read on, if the name is read on one. */
239
+ private receiverOf;
240
+ /**
241
+ * The `decl` rows of a `call` or `member` row (spans unset): one per
242
+ * declaration the receiver's union constituents give the member, when they
243
+ * give more than one (carrick#2448). A constituent's declaration is its
244
+ * member's ({@link attributedDeclaration}), or, for a member with none, the
245
+ * constituent type's own ({@link typeDeclaration}). Two instantiations of
246
+ * one generic class, or one class and `undefined`, give one, and no row.
247
+ * A throw writes one row flagged {@link FLAG_CHECKER_THREW}.
248
+ */
249
+ private declRows;
250
+ /** The row's symbol, following aliases to a target that has a declaration. */
251
+ symbolOf(kind: PositionKind, node: ts.Node): ts.Symbol | undefined;
252
+ /**
253
+ * In a TypeScript file `const { a } = require("m")` binds `a` as `any` with
254
+ * the binding as its only declaration (TypeScript resolves `require` itself
255
+ * only in JavaScript files), so a trace stops there. Name the export the
256
+ * call resolves to instead (carrick#2454): for the binding itself, and for
257
+ * `m.x` where `m` is a whole-module binding. `undefined` when the name is
258
+ * not such a binding, the specifier is not a literal or does not resolve,
259
+ * or the module has no such export.
260
+ */
261
+ private requiredExport;
262
+ /** The `require` binding a symbol is, when its only declaration is one. */
263
+ private requireBinding;
264
+ /** `"m"` of a call `require("m")` to the global `require`, else `undefined`. */
265
+ private requireSpecifier;
266
+ private exportOfRequired;
267
+ private host;
268
+ private resolutionHost;
269
+ }
270
+ /** Order two `decl_file` names, `null` last. */
271
+ export declare function compareNames(a: string | null, b: string | null): number;
154
272
  /** The kind of row a node gives, if any (exported for the editor-parity test, carrick#2418). */
155
273
  export declare function kindOf(node: ts.Node): NodeKind | undefined;
@@ -53,7 +53,7 @@ import * as path from 'node:path';
53
53
  import * as zlib from 'node:zlib';
54
54
  import { ts } from 'ts-morph';
55
55
  import { WriteGuard, installedPackageDirectory, isDeclarationFileName, moduleExport } from './capture/index.js';
56
- import { attributedDeclaration, installedPackageOf } from './declaration-attribution.js';
56
+ import { attributedDeclaration, installedPackageOf, typeDeclaration } from './declaration-attribution.js';
57
57
  import { typeToStringAsDeclared } from './print-type.js';
58
58
  /** The format's version, written in the header. */
59
59
  export const POSITION_ROWS_VERSION = 4;
@@ -76,6 +76,17 @@ export const FLAG_TOO_MANY = 16;
76
76
  export const FLAG_PUBLISHED = 32;
77
77
  /** The declaration is what its module exports as `export =` or `default` (carrick#2508). */
78
78
  export const FLAG_MODULE_DEFAULT = 64;
79
+ /**
80
+ * A `call` row only: the call's declared return is the result of the
81
+ * function it is handed (`ReturnType<F>`, a bare type parameter the handed
82
+ * function returns, or an awaitable of one), so the library runs it and
83
+ * hands its result back (carrick#2634). Set when the call passes at least
84
+ * one argument at a function-typed parameter and every such parameter
85
+ * meets that return. The last free bit of the `u8`: the next flag widens
86
+ * the field and bumps the format. Pinned to `FLAG_RUNS_HANDED` in
87
+ * `src/position_rows.rs` by `position-rows-runs-handed.test.ts`.
88
+ */
89
+ export const FLAG_RUNS_HANDED = 128;
79
90
  /** The most `decl` rows one position lists. */
80
91
  export const DECL_CAP = 16;
81
92
  const COMPARE_OPERATORS = new Set([
@@ -102,7 +113,7 @@ export function writePositionRows(options) {
102
113
  const { loader, files, scanRoot, outPath, service } = options;
103
114
  const outDir = path.dirname(outPath);
104
115
  const guard = WriteGuard.of({ dirs: [outDir], protect: [loader.getRepoRoot(), scanRoot] });
105
- const paths = new PathNames(scanRoot);
116
+ const paths = new PathNames(scanRoot, (file) => loader.packageDirectoryOf(file));
106
117
  const lines = new Array(files.length);
107
118
  const counts = {
108
119
  files: files.length,
@@ -256,8 +267,15 @@ function fileLine(line) {
256
267
  * through a link still contains its files), `lib:<name>` for the compiler's
257
268
  * default library, `pkg:<name>/<path>` for an installed package outside the
258
269
  * root, and nothing otherwise.
270
+ *
271
+ * An installed package outside the root is found by its path's last
272
+ * `node_modules` segment, else by `packageDirectoryOf`: the module graph's
273
+ * answer where the resolver serves a package from a cache whose path has no
274
+ * `node_modules` segment (carrick#2599). Either way the directory must hold a
275
+ * package.json.
259
276
  */
260
277
  export class PathNames {
278
+ packageDirectoryOf;
261
279
  roots;
262
280
  packageNames = new Map();
263
281
  /**
@@ -267,7 +285,8 @@ export class PathNames {
267
285
  */
268
286
  declaringFiles = new Map();
269
287
  declaringPackages = new Map();
270
- constructor(scanRoot) {
288
+ constructor(scanRoot, packageDirectoryOf = () => undefined) {
289
+ this.packageDirectoryOf = packageDirectoryOf;
271
290
  const resolved = path.resolve(scanRoot);
272
291
  let real = resolved;
273
292
  try {
@@ -306,7 +325,7 @@ export class PathNames {
306
325
  const inside = this.inside(fileName);
307
326
  if (inside)
308
327
  return toSlashes(inside.rel);
309
- const installed = installedPackageDirectory(this.roots[0], fileName);
328
+ const installed = installedPackageDirectory(this.roots[0], fileName) ?? this.packageDirectoryOf(fileName);
310
329
  if (installed && fs.existsSync(path.join(installed.directory, 'package.json'))) {
311
330
  return `pkg:${installed.name}/${toSlashes(path.relative(installed.directory, fileName))}`;
312
331
  }
@@ -381,8 +400,12 @@ export class PathNames {
381
400
  function toSlashes(p) {
382
401
  return p.split(path.sep).join('/');
383
402
  }
384
- /** The rows of one program's files. */
385
- class PositionWalker {
403
+ /**
404
+ * The rows of one program's files. The `implementations` action
405
+ * (`implementations.ts`, carrick#2432) reads a call's symbol and names its
406
+ * answers through the same walker, so they join as the rows do.
407
+ */
408
+ export class PositionWalker {
386
409
  program;
387
410
  paths;
388
411
  loader;
@@ -426,6 +449,8 @@ class PositionWalker {
426
449
  if (type.flags & ts.TypeFlags.Any) {
427
450
  flags |= type.intrinsicName === 'error' ? FLAG_ERROR_TYPE : FLAG_ANY;
428
451
  }
452
+ if (kind === 'call' && this.runsHanded(node))
453
+ flags |= FLAG_RUNS_HANDED;
429
454
  const typeText = this.paths.scrubType(typeToStringAsDeclared(this.checker, type, undefined));
430
455
  if (!symbol)
431
456
  return [kind, start, end, null, null, null, null, typeText, flags];
@@ -453,6 +478,114 @@ class PositionWalker {
453
478
  return [kind, start, end, null, null, null, null, null, FLAG_CHECKER_THREW];
454
479
  }
455
480
  }
481
+ /**
482
+ * Whether a call's declared return is the result of the function it is
483
+ * handed (carrick#2634), read from the declared signature through public
484
+ * checker calls. See {@link FLAG_RUNS_HANDED}.
485
+ */
486
+ runsHanded(node) {
487
+ if (!ts.isCallExpression(node) && !ts.isNewExpression(node))
488
+ return false;
489
+ const args = node.arguments ?? [];
490
+ if (args.length === 0)
491
+ return false;
492
+ try {
493
+ const declaration = this.checker.getResolvedSignature(node)?.declaration;
494
+ if (!declaration || ts.isJSDocSignature(declaration))
495
+ return false;
496
+ const declared = this.checker.getSignatureFromDeclaration(declaration);
497
+ if (!declared)
498
+ return false;
499
+ const own = new Set(declared.getTypeParameters() ?? []);
500
+ const results = new Map();
501
+ const resultOf = (f) => {
502
+ let atom = results.get(f);
503
+ if (!atom)
504
+ results.set(f, (atom = {}));
505
+ return atom;
506
+ };
507
+ const atoms = (t, out, depth = 0) => {
508
+ if (depth > 8)
509
+ return out;
510
+ if (t.flags & ts.TypeFlags.TypeParameter) {
511
+ if (own.has(t))
512
+ out.add(t);
513
+ }
514
+ else if (t.flags & ts.TypeFlags.UnionOrIntersection) {
515
+ for (const member of t.types)
516
+ atoms(member, out, depth + 1);
517
+ }
518
+ else if (t.flags & ts.TypeFlags.Conditional) {
519
+ const f = resultOfConditional(t, own);
520
+ if (f)
521
+ out.add(resultOf(f));
522
+ }
523
+ else if (isReference(t) && this.isAwaitable(t)) {
524
+ for (const arg of this.checker.getTypeArguments(t))
525
+ atoms(arg, out, depth + 1);
526
+ }
527
+ return out;
528
+ };
529
+ const returned = atoms(this.checker.getReturnTypeOfSignature(declared), new Set());
530
+ if (returned.size === 0)
531
+ return false;
532
+ const parameters = declared.getParameters();
533
+ let handed = 0;
534
+ for (let i = 0; i < args.length; i++) {
535
+ const parameter = parameters[Math.min(i, parameters.length - 1)];
536
+ if (!parameter)
537
+ continue;
538
+ const isRest = parameter.valueDeclaration !== undefined &&
539
+ ts.isParameter(parameter.valueDeclaration) &&
540
+ parameter.valueDeclaration.dotDotDotToken !== undefined;
541
+ if (!isRest && i >= parameters.length)
542
+ continue;
543
+ let type = this.checker.getTypeOfSymbolAtLocation(parameter, declaration);
544
+ if (isRest) {
545
+ if (!isReference(type))
546
+ continue;
547
+ const [element] = this.checker.getTypeArguments(type);
548
+ if (!element)
549
+ continue;
550
+ type = element;
551
+ }
552
+ const signatures = this.callSignaturesOf(type);
553
+ if (signatures.length === 0)
554
+ continue;
555
+ handed++;
556
+ const mine = new Set();
557
+ if (type.flags & ts.TypeFlags.TypeParameter)
558
+ mine.add(resultOf(type));
559
+ else
560
+ for (const signature of signatures)
561
+ atoms(this.checker.getReturnTypeOfSignature(signature), mine);
562
+ if (![...mine].some((atom) => returned.has(atom)))
563
+ return false;
564
+ }
565
+ return handed > 0;
566
+ }
567
+ catch {
568
+ return false;
569
+ }
570
+ }
571
+ /** The call signatures of a parameter's type, a type parameter read through its constraint, `null` and `undefined` skipped. */
572
+ callSignaturesOf(type) {
573
+ let t = type;
574
+ if (t.flags & ts.TypeFlags.TypeParameter)
575
+ t = this.checker.getBaseConstraintOfType(t) ?? t;
576
+ if (t.flags & ts.TypeFlags.Union) {
577
+ const kept = t.types.filter((m) => !(m.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)));
578
+ if (kept.length !== 1)
579
+ return [];
580
+ t = kept[0];
581
+ }
582
+ return this.checker.getSignaturesOfType(t, ts.SignatureKind.Call);
583
+ }
584
+ /** The compiler's own awaited type differs from the type: `Promise<R>`, `PromiseLike<R>`. */
585
+ isAwaitable(t) {
586
+ const awaited = this.checker.getAwaitedType(t);
587
+ return awaited !== undefined && awaited !== t;
588
+ }
456
589
  /**
457
590
  * An intrinsic element's type: the attributes `JSX.IntrinsicElements`
458
591
  * gives its tag. The compiler types an intrinsic tag name itself as the
@@ -495,8 +628,7 @@ class PositionWalker {
495
628
  }
496
629
  /** The declaration of a type's symbol, else of its alias symbol: a mapped type node, or the alias naming it. */
497
630
  typeDeclaration(type) {
498
- const owner = type.getSymbol() ?? type.aliasSymbol;
499
- return attributedDeclaration(() => this.program, owner?.declarations ?? []);
631
+ return typeDeclaration(() => this.program, type);
500
632
  }
501
633
  /**
502
634
  * How `declaration`'s module publishes `symbol`: {@link FLAG_PUBLISHED}
@@ -742,7 +874,7 @@ function tail(row) {
742
874
  return [row[3], row[4], row[5], row[6], row[7], row[8]];
743
875
  }
744
876
  /** Order two `decl_file` names, `null` last. */
745
- function compareNames(a, b) {
877
+ export function compareNames(a, b) {
746
878
  if (a === b)
747
879
  return 0;
748
880
  if (a === null)
@@ -751,6 +883,28 @@ function compareNames(a, b) {
751
883
  return -1;
752
884
  return a < b ? -1 : 1;
753
885
  }
886
+ function isReference(t) {
887
+ return !!(t.flags & ts.TypeFlags.Object) && !!(t.objectFlags & ts.ObjectFlags.Reference);
888
+ }
889
+ /**
890
+ * The type parameter `F` of a conditional written `F extends (...) => infer R ? R : _`
891
+ * (`ReturnType<F>`): the result of `F`. `Parameters<F>` and the like infer
892
+ * elsewhere and give nothing.
893
+ */
894
+ function resultOfConditional(t, own) {
895
+ if (!(t.checkType.flags & ts.TypeFlags.TypeParameter) || !own.has(t.checkType))
896
+ return undefined;
897
+ const node = t.root.node;
898
+ if (!ts.isFunctionTypeNode(node.extendsType))
899
+ return undefined;
900
+ const returns = node.extendsType.type;
901
+ if (!ts.isInferTypeNode(returns))
902
+ return undefined;
903
+ const yielded = node.trueType;
904
+ if (!ts.isTypeReferenceNode(yielded) || !ts.isIdentifier(yielded.typeName))
905
+ return undefined;
906
+ return yielded.typeName.text === returns.typeParameter.name.text ? t.checkType : undefined;
907
+ }
754
908
  /** The kind of row a node gives, if any (exported for the editor-parity test, carrick#2418). */
755
909
  export function kindOf(node) {
756
910
  if (ts.isCallExpression(node) || ts.isNewExpression(node) || ts.isTaggedTemplateExpression(node)) {
@@ -182,6 +182,21 @@ export declare class ProjectLoader {
182
182
  * through Deno, and for a file the workspace itself owns.
183
183
  */
184
184
  packageOf(filePath: string): string | undefined;
185
+ /**
186
+ * The installed package directory a resolved file lies in, and its name,
187
+ * when the module graph places it (carrick#2599). `undefined` for a project
188
+ * that did not resolve through Deno: there the path says it.
189
+ */
190
+ packageDirectoryOf(filePath: string): {
191
+ directory: string;
192
+ name: string;
193
+ } | undefined;
194
+ /**
195
+ * How the module graph resolves `name` from `from`, as the program did
196
+ * (carrick#2599). `undefined` for a project that did not resolve through
197
+ * Deno: there Node resolution is the program's.
198
+ */
199
+ resolveThroughGraph(name: string, from: string, options: import('typescript').CompilerOptions): import('typescript').ResolvedModuleFull | undefined;
185
200
  /**
186
201
  * Check if the project has been successfully initialized
187
202
  */
@@ -502,6 +502,22 @@ export class ProjectLoader {
502
502
  packageOf(filePath) {
503
503
  return this.denoProject?.packageOf(filePath);
504
504
  }
505
+ /**
506
+ * The installed package directory a resolved file lies in, and its name,
507
+ * when the module graph places it (carrick#2599). `undefined` for a project
508
+ * that did not resolve through Deno: there the path says it.
509
+ */
510
+ packageDirectoryOf(filePath) {
511
+ return this.denoProject?.packageDirectoryOf(filePath);
512
+ }
513
+ /**
514
+ * How the module graph resolves `name` from `from`, as the program did
515
+ * (carrick#2599). `undefined` for a project that did not resolve through
516
+ * Deno: there Node resolution is the program's.
517
+ */
518
+ resolveThroughGraph(name, from, options) {
519
+ return this.denoProject?.resolve(name, from, options);
520
+ }
505
521
  /**
506
522
  * Check if the project has been successfully initialized
507
523
  */
@@ -479,11 +479,29 @@ export declare class TypeInferrer {
479
479
  * guard, so that binding stays unread and the capture answers the row.
480
480
  */
481
481
  private destructuredValueTerminal;
482
+ /**
483
+ * Between `callExpr` and the return statement around it there is an object
484
+ * or array literal: the call's result is one part of a value the function
485
+ * builds and returns.
486
+ */
487
+ private callIsPartOfReturnedLiteral;
482
488
  /**
483
489
  * `expr` declares a name for what a call returns when it is handed a
484
490
  * tracked name whole (`const data: T = await parseJson(response, 'op')`).
485
491
  */
486
492
  private handsTrackedValueToACall;
493
+ /**
494
+ * The call whose result `expr` declares or assigns a name for, and the
495
+ * index of its argument that is a tracked name whole, or undefined.
496
+ */
497
+ private callTakingTrackedValue;
498
+ /**
499
+ * `expr` names the result of a call that states the tracked value it takes
500
+ * (`callStatesItsArgument`): a schema validates it, or the callee returns it
501
+ * unchanged. A converter's result describes what it built from the value,
502
+ * not the value (carrick#2595).
503
+ */
504
+ private statesTrackedValue;
487
505
  /** `expr` holds a binary whole-body read taken on a tracked name. */
488
506
  private holdsBinaryBodyRead;
489
507
  /**
@@ -696,7 +714,10 @@ export declare class TypeInferrer {
696
714
  * serialiser answering `string` describes what the caller did with the
697
715
  * body, not what the body is, and publishing it would be a
698
716
  * concrete-but-wrong contract where the honest `any` of the read is
699
- * merely unresolved.
717
+ * merely unresolved;
718
+ * - the call states its argument (`callStatesItsArgument`): a schema
719
+ * validates it, or the callee returns it unchanged. A converter's
720
+ * object result describes what it built, not the body (carrick#2595).
700
721
  */
701
722
  private statedPayloadAroundBodyRead;
702
723
  /**
@@ -1906,6 +1927,62 @@ export declare class TypeInferrer {
1906
1927
  * whose type does not resolve the member, or an opaque config, abstains.
1907
1928
  */
1908
1929
  private requestBodyInCall;
1930
+ /**
1931
+ * carrick#2628: the located node is an argument of a call into a function
1932
+ * whose body the program holds (an in-repo client method,
1933
+ * `client.addTags(project, unique(tags))`), at a parameter that is not a
1934
+ * body slot. What the call sends is decided inside that function, so the
1935
+ * argument is the body only when the function sends it unchanged. One
1936
+ * level, read off each use of the parameter in the function's body:
1937
+ *
1938
+ * - the use IS the value of a body-named member (`body: tags`,
1939
+ * `body: JSON.stringify(tags)`) or of a body slot of a call: the
1940
+ * argument is the body, and its own type stands (`none`);
1941
+ * - the use sits inside such a value (`body: { tags }`,
1942
+ * `body: (event ?? {}) as never`): the body is that value, read at the
1943
+ * function without the casts around it;
1944
+ * - the use sits inside an object or array literal that is no body value
1945
+ * (`send(project, [labels])`): the body cannot be told, abstain.
1946
+ *
1947
+ * Uses that disagree abstain. A generic function's body may be typed by
1948
+ * its type parameters, so it abstains too. A library's declaration
1949
+ * (`fetch`, an installed client) has no body to read and is left alone,
1950
+ * and so is an untyped argument (a handler's `request.body` handed to a
1951
+ * helper): it states no contract to mistake, and the untyped-read path
1952
+ * below reads it.
1953
+ */
1954
+ private bodyBuiltByCallee;
1955
+ /**
1956
+ * The request body value `use` is part of, inside `scope`: the value of a
1957
+ * body-named object member, or the argument at a body slot of a call,
1958
+ * looking through parentheses, casts, `await` and a `JSON.stringify`
1959
+ * around it. `use` itself when it is that value whole.
1960
+ */
1961
+ private bodyValueAround;
1962
+ /** `value` is `use` behind what `sentValue` sees through. */
1963
+ private isSameValue;
1964
+ /**
1965
+ * The value a body slot sends when it sends anything, behind parentheses,
1966
+ * casts, `await`, a `JSON.stringify`, and (carrick#2668) a choice whose
1967
+ * other side sends nothing: `x ? JSON.stringify(x) : undefined`,
1968
+ * `x || null`, `x ?? undefined`. A `?? {}` sends `{}`, so it is a body the
1969
+ * function builds and is not seen through.
1970
+ */
1971
+ private sentValue;
1972
+ /**
1973
+ * The branch of `choice` that sends something, when its other branch sends
1974
+ * nothing (`undefined`, `null`, `void 0`, or `{}` spread into a request).
1975
+ */
1976
+ private sendingBranch;
1977
+ /** `undefined`, `null`, `void 0`, or (where `emptyObject`) `{}`. */
1978
+ private sendsNothing;
1979
+ /**
1980
+ * carrick#2668, #2664: `use` sits in the test of a choice whose other side
1981
+ * sends nothing (`body ? JSON.stringify(body) : null`,
1982
+ * `...(body === undefined ? {} : { body: JSON.stringify(body) })`). The
1983
+ * test only decides whether the argument is sent.
1984
+ */
1985
+ private inSendNothingTest;
1909
1986
  /** A string, a string literal, a template literal, or a union of strings. */
1910
1987
  private isStringLikeType;
1911
1988
  /**
@@ -2072,6 +2149,22 @@ export declare class TypeInferrer {
2072
2149
  * `reads.parameters`, the parameter's own type (rank 4).
2073
2150
  */
2074
2151
  private stateAtReceivingCall;
2152
+ /**
2153
+ * The input contract of a schema `call` validates its argument at `index`
2154
+ * with: its receiver (`Schema.safeParse(body)`) or one of its other
2155
+ * arguments (`parse(Schema, body)`), or null. A candidate counts only when
2156
+ * it declares schema types, so no method or library name is matched
2157
+ * (carrick#1166).
2158
+ */
2159
+ private schemaHandedArgument;
2160
+ /**
2161
+ * `call`'s result describes the value it takes at argument `index`: it
2162
+ * validates it with a schema, or its callee returns it unchanged
2163
+ * (`passThroughFunction`). Any other call builds something new from the
2164
+ * value, and its result describes what it built, never the value it was
2165
+ * handed (carrick#2595).
2166
+ */
2167
+ private callStatesItsArgument;
2075
2168
  /**
2076
2169
  * The project function `call` invokes, when every value it returns is its
2077
2170
  * argument at `index` as it was handed in (through parentheses, casts,