@cplieger/deadset-ts 8.0.0-dev.15 → 8.0.0-dev.17
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/src/alias-chain.js +0 -5
- package/dist/src/amd.js +81 -0
- package/dist/src/analysis.js +94 -54
- package/dist/src/augmentations.js +23 -24
- package/dist/src/bindings.js +382 -0
- package/dist/src/calls.js +25 -8
- package/dist/src/commands/read.js +6 -7
- package/dist/src/commands/tools.js +5 -9
- package/dist/src/component-files.js +3 -2
- package/dist/src/conformance-record.js +1 -1
- package/dist/src/consumers.js +9 -10
- package/dist/src/contextual-uses.js +1 -17
- package/dist/src/contract/config.generated.js +5 -2
- package/dist/src/contract/contract.generated.js +119 -2
- package/dist/src/contract/report.generated.js +6 -2
- package/dist/src/dependencies.js +98 -71
- package/dist/src/destructuring.js +1 -19
- package/dist/src/element-access.js +179 -164
- package/dist/src/entries/build-scripts.js +222 -0
- package/dist/src/{configuration-files.js → entries/configuration-files.js} +22 -64
- package/dist/src/{convention-rows.js → entries/convention-rows.js} +120 -27
- package/dist/src/entries/conventions.js +739 -0
- package/dist/src/{html-entries.js → entries/html-entries.js} +9 -12
- package/dist/src/{mdx-entries.js → entries/mdx-entries.js} +3 -3
- package/dist/src/entries/run-directories.js +77 -0
- package/dist/src/entries/sources.js +144 -0
- package/dist/src/entries/static-module.js +670 -0
- package/dist/src/entries/test-runners.js +684 -0
- package/dist/src/{workflow-steps.js → entries/workflow-steps.js} +18 -8
- package/dist/src/extensions.js +37 -0
- package/dist/src/facts.js +38 -0
- package/dist/src/findings/completion.js +40 -4
- package/dist/src/findings/emitters.js +5 -8
- package/dist/src/{implementations.js → findings/implementations.js} +3 -3
- package/dist/src/{in-operands.js → findings/in-operands.js} +2 -2
- package/dist/src/findings/self-check.js +36 -20
- package/dist/src/findings-pass.js +5 -6
- package/dist/src/framework-lifecycle.js +42 -15
- package/dist/src/fs/manifest.js +15 -20
- package/dist/src/generated-file.js +172 -29
- package/dist/src/graph.js +14 -8
- package/dist/src/import-bindings.js +73 -28
- package/dist/src/index/sites.js +557 -0
- package/dist/src/index.js +1 -1
- package/dist/src/indexed-access.js +523 -478
- package/dist/src/injection-container.js +1 -1
- package/dist/src/interface-satisfaction.js +1 -1
- package/dist/src/inventory/commonjs.js +62 -17
- package/dist/src/inventory/enumerate.js +2 -1
- package/dist/src/javascript-file.js +26 -11
- package/dist/src/keyof-comparisons.js +124 -103
- package/dist/src/load/classify.js +28 -9
- package/dist/src/load/diagnostics.js +8 -1
- package/dist/src/load/discover.js +15 -7
- package/dist/src/load/expected-module.js +2 -2
- package/dist/src/load/plan.js +2 -2
- package/dist/src/load/specifiers.js +2 -4
- package/dist/src/load/synthesize.js +10 -5
- package/dist/src/load/workspace-manifests.js +1 -1
- package/dist/src/load/workspace-resolution.js +2 -2
- package/dist/src/matrix.js +12 -17
- package/dist/src/module-declarations.js +70 -85
- package/dist/src/overrides.js +134 -112
- package/dist/src/paths.js +56 -1
- package/dist/src/platform-calls.js +78 -0
- package/dist/src/platform-symbols.js +134 -0
- package/dist/src/references/read-rule.js +1 -0
- package/dist/src/references/read-rules.js +48 -0
- package/dist/src/references/sink.js +151 -0
- package/dist/src/references/sources.js +450 -0
- package/dist/src/references.js +111 -1116
- package/dist/src/resolve.js +1 -1
- package/dist/src/{configured-declarations.js → roots/configured-declarations.js} +7 -4
- package/dist/src/{entry-point-gaps.js → roots/entry-point-gaps.js} +5 -8
- package/dist/src/{manifest.js → roots/manifest.js} +4 -4
- package/dist/src/roots/published-reach.js +412 -0
- package/dist/src/roots/root-set.js +489 -0
- package/dist/src/roots/unseen-loads.js +236 -0
- package/dist/src/serialization-contract.js +9 -4
- package/dist/src/source-files.js +5 -9
- package/dist/src/stores.js +4 -2
- package/dist/src/suppress.js +30 -32
- package/dist/src/sweep.js +25 -13
- package/dist/src/symbol-keys.js +89 -83
- package/dist/src/tests/file-class.js +76 -0
- package/dist/src/{outside-tests.js → tests/outside.js} +7 -7
- package/dist/src/{test-support.js → tests/support.js} +5 -12
- package/dist/src/type-parameter-reads.js +178 -139
- package/dist/src/unimplemented-callees.js +262 -242
- package/dist/src/verbs/analyze.js +15 -3
- package/dist/src/verbs/describe.js +5 -3
- package/dist/src/verbs/explain.js +50 -28
- package/dist/src/verbs/print-retained.js +2 -2
- package/jsr.json +1 -1
- package/package.json +3 -3
- package/src/alias-chain.ts +0 -7
- package/src/amd.ts +130 -0
- package/src/analysis.ts +156 -70
- package/src/augmentations.ts +41 -27
- package/src/automatic-types.ts +1 -1
- package/src/bindings.ts +460 -0
- package/src/calls.ts +25 -7
- package/src/commands/read.ts +6 -8
- package/src/commands/tools.ts +5 -11
- package/src/component-files.ts +4 -2
- package/src/conformance-record.ts +1 -1
- package/src/consumers.ts +12 -11
- package/src/contextual-uses.ts +2 -22
- package/src/contract/config.generated.ts +5 -2
- package/src/contract/contract.generated.ts +138 -2
- package/src/contract/report.generated.ts +6 -2
- package/src/dependencies.ts +117 -71
- package/src/destructuring.ts +1 -31
- package/src/element-access.ts +188 -182
- package/src/entries/build-scripts.ts +292 -0
- package/src/{configuration-files.ts → entries/configuration-files.ts} +33 -82
- package/src/{convention-rows.ts → entries/convention-rows.ts} +167 -28
- package/src/{conventions.ts → entries/conventions.ts} +349 -523
- package/src/{html-entries.ts → entries/html-entries.ts} +19 -18
- package/src/{mdx-entries.ts → entries/mdx-entries.ts} +5 -5
- package/src/entries/run-directories.ts +108 -0
- package/src/entries/sources.ts +266 -0
- package/src/entries/static-module.ts +858 -0
- package/src/entries/test-runners.ts +868 -0
- package/src/{workflow-steps.ts → entries/workflow-steps.ts} +29 -11
- package/src/exempt.ts +3 -2
- package/src/extensions.ts +45 -0
- package/src/facts.ts +46 -0
- package/src/file-facts.ts +1 -1
- package/src/findings/boundary.ts +2 -0
- package/src/findings/completion.ts +43 -4
- package/src/findings/emitter.ts +1 -1
- package/src/findings/emitters.ts +14 -10
- package/src/{implementations.ts → findings/implementations.ts} +4 -4
- package/src/{in-operands.ts → findings/in-operands.ts} +3 -3
- package/src/findings/self-check.ts +41 -22
- package/src/findings/visibility-narrowing.ts +1 -1
- package/src/findings-pass.ts +5 -12
- package/src/framework-lifecycle.ts +43 -15
- package/src/fs/manifest.ts +25 -21
- package/src/generated-file.ts +240 -36
- package/src/graph.ts +27 -11
- package/src/import-bindings.ts +98 -29
- package/src/index/sites.ts +781 -0
- package/src/index.ts +1 -1
- package/src/indexed-access.ts +570 -527
- package/src/injection-container.ts +1 -1
- package/src/interface-satisfaction.ts +1 -1
- package/src/inventory/commonjs.ts +102 -17
- package/src/inventory/enumerate.ts +2 -1
- package/src/javascript-file.ts +29 -12
- package/src/keyof-comparisons.ts +131 -116
- package/src/load/classify.ts +49 -13
- package/src/load/diagnostics.ts +11 -1
- package/src/load/discover.ts +27 -11
- package/src/load/expected-module.ts +8 -2
- package/src/load/plan.ts +11 -2
- package/src/load/specifiers.ts +8 -5
- package/src/load/synthesize.ts +12 -6
- package/src/load/test-globals.ts +1 -1
- package/src/load/workspace-manifests.ts +1 -1
- package/src/load/workspace-resolution.ts +9 -2
- package/src/load/workspace-run.ts +1 -1
- package/src/matrix.ts +13 -17
- package/src/module-declarations.ts +74 -98
- package/src/overrides.ts +162 -134
- package/src/paths.ts +65 -1
- package/src/platform-calls.ts +119 -0
- package/src/platform-symbols.ts +189 -0
- package/src/references/read-rule.ts +60 -0
- package/src/references/read-rules.ts +55 -0
- package/src/references/sink.ts +213 -0
- package/src/references/sources.ts +632 -0
- package/src/references.ts +174 -1492
- package/src/report.ts +2 -2
- package/src/resolve.ts +1 -1
- package/src/{configured-declarations.ts → roots/configured-declarations.ts} +10 -7
- package/src/{entry-point-gaps.ts → roots/entry-point-gaps.ts} +5 -8
- package/src/{manifest.ts → roots/manifest.ts} +5 -5
- package/src/roots/published-reach.ts +481 -0
- package/src/{roots.ts → roots/root-set.ts} +203 -630
- package/src/roots/unseen-loads.ts +345 -0
- package/src/serialization-contract.ts +9 -4
- package/src/source-files.ts +5 -10
- package/src/stores.ts +13 -2
- package/src/suppress.ts +48 -33
- package/src/sweep.ts +37 -14
- package/src/symbol-keys.ts +102 -102
- package/src/tests/file-class.ts +118 -0
- package/src/{outside-tests.ts → tests/outside.ts} +16 -10
- package/src/{test-support.ts → tests/support.ts} +15 -21
- package/src/type-parameter-reads.ts +187 -158
- package/src/unimplemented-callees.ts +297 -280
- package/src/verbs/analyze.ts +19 -5
- package/src/verbs/describe.ts +5 -2
- package/src/verbs/explain.ts +75 -32
- package/src/verbs/print-retained.ts +2 -2
- package/dist/src/build-scripts.js +0 -418
- package/dist/src/conventions.js +0 -907
- package/dist/src/entry-points.js +0 -444
- package/dist/src/own-body.js +0 -28
- package/dist/src/roots.js +0 -865
- package/dist/src/unseen-loads.js +0 -189
- package/src/build-scripts.ts +0 -536
- package/src/entry-points.ts +0 -584
- package/src/own-body.ts +0 -42
- package/src/unseen-loads.ts +0 -282
package/src/element-access.ts
CHANGED
|
@@ -41,12 +41,8 @@ import {
|
|
|
41
41
|
type SourceFile,
|
|
42
42
|
} from "@typescript/native/ast";
|
|
43
43
|
import type { Type } from "@typescript/native/sync";
|
|
44
|
-
import type { AliasChains } from "./alias-chain.ts";
|
|
45
|
-
import { nodeKey, type Inventory } from "./inventory.ts";
|
|
46
|
-
import { renderPosition } from "./position.ts";
|
|
47
44
|
import { UNANSWERED } from "./query.ts";
|
|
48
|
-
import type {
|
|
49
|
-
import type { ProjectView } from "./session.ts";
|
|
45
|
+
import type { Read, ReadRule } from "./references/read-rule.ts";
|
|
50
46
|
import { parenthesesRemoved } from "./unwrap.ts";
|
|
51
47
|
|
|
52
48
|
type Use = "read" | "write" | "both";
|
|
@@ -242,190 +238,200 @@ interface Candidate {
|
|
|
242
238
|
}
|
|
243
239
|
|
|
244
240
|
/**
|
|
245
|
-
* The
|
|
246
|
-
*
|
|
241
|
+
* The reads the element accesses of a side's files make of the members their index's literal
|
|
242
|
+
* type names, each made by the declaration holding the access or the call. A type the checker
|
|
243
|
+
* leaves unanswered holds what its answer could have read.
|
|
247
244
|
*/
|
|
248
|
-
export
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
calls
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
break;
|
|
326
|
-
}
|
|
327
|
-
if (use === name || symbolOf.get(use) !== symbol) {
|
|
328
|
-
continue;
|
|
329
|
-
}
|
|
330
|
-
const parent = use.parent;
|
|
331
|
-
found =
|
|
332
|
-
isCallExpression(parent) && parent.expression === use ? [...found, parent] : undefined;
|
|
333
|
-
}
|
|
334
|
-
callsOf.set(name, found);
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
const lookups: Lookup[] = [];
|
|
338
|
-
for (const candidate of candidates) {
|
|
339
|
-
const deferred = parameterOf.get(candidate);
|
|
340
|
-
const sites = deferred === undefined ? undefined : callsOf.get(deferred.callable.name);
|
|
341
|
-
if (deferred === undefined || sites === undefined) {
|
|
342
|
-
lookups.push({
|
|
343
|
-
file: candidate.file,
|
|
344
|
-
from: candidate.from,
|
|
345
|
-
at: candidate.access.argumentExpression,
|
|
346
|
-
object: candidate.access.expression,
|
|
347
|
-
index: candidate.access.argumentExpression,
|
|
348
|
-
use: candidate.use,
|
|
349
|
-
});
|
|
350
|
-
continue;
|
|
351
|
-
}
|
|
352
|
-
// An object that is a parameter too is read as the argument each call passes there.
|
|
353
|
-
const object = parenthesesRemoved(candidate.access.expression);
|
|
354
|
-
const objectAt = isIdentifier(object)
|
|
355
|
-
? deferred.callable.parameters.findIndex(
|
|
356
|
-
(parameter) => isIdentifier(parameter.name) && parameter.name.text === object.text,
|
|
357
|
-
)
|
|
358
|
-
: -1;
|
|
359
|
-
for (const call of sites) {
|
|
360
|
-
const parameter = deferred.callable.parameters[deferred.at];
|
|
361
|
-
const index = call.arguments[deferred.at] ?? parameter?.initializer;
|
|
362
|
-
const site = calls.get(call);
|
|
363
|
-
if (index === undefined || site === undefined) {
|
|
364
|
-
continue;
|
|
365
|
-
}
|
|
366
|
-
lookups.push({
|
|
367
|
-
file: site.file,
|
|
368
|
-
from: site.from,
|
|
369
|
-
at: call,
|
|
370
|
-
object:
|
|
371
|
-
(objectAt < 0 ? undefined : call.arguments[objectAt]) ?? candidate.access.expression,
|
|
372
|
-
index,
|
|
373
|
-
use: candidate.use,
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
const nodes = lookups.flatMap((one) => [one.index, one.object]);
|
|
379
|
-
const types = queries.typesAt(nodes);
|
|
380
|
-
const typeOf = (node: Node, at: number): Type | undefined => {
|
|
381
|
-
const type = types[at];
|
|
382
|
-
return nodes[at] === node && type !== UNANSWERED ? type : undefined;
|
|
383
|
-
};
|
|
384
|
-
// A type parameter's body serves every instantiation, so it reads what its constraint admits.
|
|
385
|
-
const keysOf = (type: Type): Type => {
|
|
386
|
-
if (!type.isTypeParameter()) {
|
|
387
|
-
return type;
|
|
388
|
-
}
|
|
389
|
-
const constraint = queries.constraintOf(type);
|
|
390
|
-
return constraint === UNANSWERED || constraint === undefined ? type : constraint;
|
|
391
|
-
};
|
|
392
|
-
const partsOf = (type: Type): readonly Type[] => {
|
|
393
|
-
const parts = queries.constituents(type);
|
|
394
|
-
return parts === UNANSWERED ? [type] : parts;
|
|
395
|
-
};
|
|
245
|
+
export const elementAccess: ReadRule = {
|
|
246
|
+
start() {
|
|
247
|
+
const candidates: Candidate[] = [];
|
|
248
|
+
const calls = new Map<Node, { readonly file: SourceFile; readonly from: string }>();
|
|
249
|
+
const names: Identifier[] = [];
|
|
250
|
+
return {
|
|
251
|
+
visit(node, { file, from }) {
|
|
252
|
+
if (isElementAccessExpression(node) && !isLiteralIndex(node.argumentExpression)) {
|
|
253
|
+
candidates.push({ file, from, access: node, use: useOf(node) });
|
|
254
|
+
}
|
|
255
|
+
if (isCallExpression(node)) {
|
|
256
|
+
calls.set(node, { file, from });
|
|
257
|
+
}
|
|
258
|
+
if (isIdentifier(node)) {
|
|
259
|
+
names.push(node);
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
reads({ project, chains }) {
|
|
263
|
+
const found: Read[] = [];
|
|
264
|
+
if (candidates.length === 0) {
|
|
265
|
+
return found;
|
|
266
|
+
}
|
|
267
|
+
const queries = project.queries;
|
|
268
|
+
// A parameter index is decided at the calls only where the function is a callable every
|
|
269
|
+
// use of which is a call, so the symbols of the parameters and of every name are read.
|
|
270
|
+
const parameterOf = new Map<Candidate, { callable: Callable; at: number }>();
|
|
271
|
+
const byCallable = new Map<Identifier, Candidate[]>();
|
|
272
|
+
for (const candidate of candidates) {
|
|
273
|
+
const index = parenthesesRemoved(candidate.access.argumentExpression);
|
|
274
|
+
const fn = isIdentifier(index) ? enclosingFunction(candidate.access) : undefined;
|
|
275
|
+
const callable = fn === undefined ? undefined : callableOf(fn);
|
|
276
|
+
if (callable === undefined || !isIdentifier(index)) {
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
const at = callable.parameters.findIndex(
|
|
280
|
+
(parameter) => isIdentifier(parameter.name) && parameter.name.text === index.text,
|
|
281
|
+
);
|
|
282
|
+
if (at < 0 || assigns(callable.body, index.text)) {
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
parameterOf.set(candidate, { callable, at });
|
|
286
|
+
byCallable.set(callable.name, [...(byCallable.get(callable.name) ?? []), candidate]);
|
|
287
|
+
}
|
|
288
|
+
const callableNames = [...byCallable.keys()];
|
|
289
|
+
const spelled = new Set(callableNames.map((name) => name.text));
|
|
290
|
+
const sameName = names.filter((name) => spelled.has(name.text));
|
|
291
|
+
const asked = [...callableNames, ...sameName];
|
|
292
|
+
const symbols = queries.symbolsAt(asked);
|
|
293
|
+
const symbolOf = new Map<Node, unknown>();
|
|
294
|
+
asked.forEach((node, at) => {
|
|
295
|
+
const symbol = symbols[at];
|
|
296
|
+
if (symbol !== undefined) {
|
|
297
|
+
symbolOf.set(node, symbol);
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
const callsOf = new Map<Node, CallExpression[] | undefined>();
|
|
301
|
+
for (const name of callableNames) {
|
|
302
|
+
const symbol = symbolOf.get(name);
|
|
303
|
+
let sites: CallExpression[] | undefined =
|
|
304
|
+
symbol === undefined || symbol === UNANSWERED ? undefined : [];
|
|
305
|
+
for (const use of sameName) {
|
|
306
|
+
if (sites === undefined) {
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
const other = symbolOf.get(use);
|
|
310
|
+
if (use === name || (other !== symbol && other !== UNANSWERED)) {
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
// A use the checker could not resolve may be the function's, read where it is not called.
|
|
314
|
+
const parent = use.parent;
|
|
315
|
+
sites =
|
|
316
|
+
other !== UNANSWERED && isCallExpression(parent) && parent.expression === use
|
|
317
|
+
? [...sites, parent]
|
|
318
|
+
: undefined;
|
|
319
|
+
}
|
|
320
|
+
callsOf.set(name, sites);
|
|
321
|
+
}
|
|
396
322
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
323
|
+
const lookups: Lookup[] = [];
|
|
324
|
+
for (const candidate of candidates) {
|
|
325
|
+
const deferred = parameterOf.get(candidate);
|
|
326
|
+
const sites = deferred === undefined ? undefined : callsOf.get(deferred.callable.name);
|
|
327
|
+
if (deferred === undefined || sites === undefined) {
|
|
328
|
+
lookups.push({
|
|
329
|
+
file: candidate.file,
|
|
330
|
+
from: candidate.from,
|
|
331
|
+
at: candidate.access.argumentExpression,
|
|
332
|
+
object: candidate.access.expression,
|
|
333
|
+
index: candidate.access.argumentExpression,
|
|
334
|
+
use: candidate.use,
|
|
335
|
+
});
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
// An object that is a parameter too is read as the argument each call passes there.
|
|
339
|
+
const object = parenthesesRemoved(candidate.access.expression);
|
|
340
|
+
const objectAt = isIdentifier(object)
|
|
341
|
+
? deferred.callable.parameters.findIndex(
|
|
342
|
+
(parameter) => isIdentifier(parameter.name) && parameter.name.text === object.text,
|
|
343
|
+
)
|
|
344
|
+
: -1;
|
|
345
|
+
for (const call of sites) {
|
|
346
|
+
const parameter = deferred.callable.parameters[deferred.at];
|
|
347
|
+
const index = call.arguments[deferred.at] ?? parameter?.initializer;
|
|
348
|
+
const site = calls.get(call);
|
|
349
|
+
if (index === undefined || site === undefined) {
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
lookups.push({
|
|
353
|
+
file: site.file,
|
|
354
|
+
from: site.from,
|
|
355
|
+
at: call,
|
|
356
|
+
object:
|
|
357
|
+
(objectAt < 0 ? undefined : call.arguments[objectAt]) ??
|
|
358
|
+
candidate.access.expression,
|
|
359
|
+
index,
|
|
360
|
+
use: candidate.use,
|
|
361
|
+
});
|
|
362
|
+
}
|
|
411
363
|
}
|
|
412
|
-
|
|
413
|
-
|
|
364
|
+
|
|
365
|
+
const nodes = lookups.flatMap((one) => [one.index, one.object]);
|
|
366
|
+
const types = queries.typesAt(nodes);
|
|
367
|
+
// A type parameter's body serves every instantiation, so it reads what its constraint admits.
|
|
368
|
+
const keysOf = (type: Type): Type => {
|
|
369
|
+
if (!type.isTypeParameter()) {
|
|
370
|
+
return type;
|
|
371
|
+
}
|
|
372
|
+
const constraint = queries.constraintOf(type);
|
|
373
|
+
return constraint === UNANSWERED || constraint === undefined ? type : constraint;
|
|
374
|
+
};
|
|
375
|
+
const partsOf = (type: Type): readonly Type[] => {
|
|
376
|
+
const parts = queries.constituents(type);
|
|
377
|
+
return parts === UNANSWERED ? [type] : parts;
|
|
378
|
+
};
|
|
379
|
+
lookups.forEach((lookup, at) => {
|
|
380
|
+
const indexType = types[2 * at];
|
|
381
|
+
const objectType = types[2 * at + 1];
|
|
382
|
+
const literals =
|
|
383
|
+
indexType === undefined || indexType === UNANSWERED
|
|
384
|
+
? undefined
|
|
385
|
+
: literalNames(partsOf(keysOf(indexType)));
|
|
386
|
+
if (indexType === UNANSWERED || objectType === UNANSWERED) {
|
|
414
387
|
found.push({
|
|
388
|
+
kind: "held",
|
|
415
389
|
from: lookup.from,
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
390
|
+
...(literals === undefined ? {} : { names: [...literals] }),
|
|
391
|
+
...(objectType === UNANSWERED || objectType === undefined
|
|
392
|
+
? literals === undefined
|
|
393
|
+
? { members: true as const }
|
|
394
|
+
: {}
|
|
395
|
+
: { types: partsOf(objectType) }),
|
|
421
396
|
});
|
|
397
|
+
return;
|
|
422
398
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
399
|
+
if (objectType === undefined || literals === undefined) {
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
for (const part of partsOf(objectType)) {
|
|
403
|
+
const properties = queries.propertiesOf(part);
|
|
404
|
+
if (properties === UNANSWERED) {
|
|
405
|
+
found.push({ kind: "held", from: lookup.from, names: [...literals] });
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
408
|
+
for (const property of properties) {
|
|
409
|
+
if (!literals.has(property.escapedName)) {
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
for (const to of chains.declarationsOf(property)) {
|
|
413
|
+
for (const use of lookup.use === "both"
|
|
414
|
+
? (["read", "write"] as const)
|
|
415
|
+
: [lookup.use]) {
|
|
416
|
+
found.push({
|
|
417
|
+
kind: "named",
|
|
418
|
+
from: lookup.from,
|
|
419
|
+
to,
|
|
420
|
+
file: lookup.file,
|
|
421
|
+
at: lookup.at,
|
|
422
|
+
use,
|
|
423
|
+
via: "keyed",
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
return found;
|
|
431
|
+
},
|
|
432
|
+
};
|
|
433
|
+
},
|
|
434
|
+
};
|
|
429
435
|
|
|
430
436
|
/** The names a union of literal types spells, or none where a constituent is no string or number literal. */
|
|
431
437
|
function literalNames(parts: readonly Type[]): ReadonlySet<string> | undefined {
|