@cplieger/deadset-ts 8.0.0-dev.16 → 8.0.0-dev.18
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 +82 -91
- package/dist/src/augmentations.js +24 -25
- package/dist/src/bindings.js +382 -0
- package/dist/src/calls.js +279 -43
- 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 +6 -9
- package/dist/src/contextual-uses.js +1 -17
- package/dist/src/contract/config.generated.js +4 -1
- package/dist/src/contract/contract.generated.js +2 -2
- package/dist/src/contract/report.generated.js +6 -2
- package/dist/src/dependencies.js +25 -29
- package/dist/src/destructuring.js +1 -19
- package/dist/src/element-access.js +179 -164
- package/dist/src/entries/build-scripts.js +2 -2
- package/dist/src/entries/configuration-files.js +3 -7
- package/dist/src/entries/conventions.js +2 -2
- package/dist/src/entries/html-entries.js +7 -10
- package/dist/src/entries/mdx-entries.js +2 -2
- package/dist/src/entries/static-module.js +2 -1
- package/dist/src/exempt.js +0 -26
- package/dist/src/exposure.js +400 -0
- package/dist/src/facts.js +4 -4
- package/dist/src/findings/completion.js +44 -21
- package/dist/src/findings/emitters.js +22 -33
- 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/intra-function.js +3 -3
- package/dist/src/findings/reads-and-writes.js +71 -15
- package/dist/src/findings/unused-declarations.js +2 -22
- package/dist/src/findings/visibility-narrowing.js +14 -20
- package/dist/src/framework-lifecycle.js +41 -14
- package/dist/src/import-bindings.js +73 -28
- package/dist/src/index/sites.js +557 -0
- package/dist/src/indexed-access.js +523 -478
- package/dist/src/interface-satisfaction.js +1 -1
- package/dist/src/inventory.js +18 -0
- package/dist/src/keyof-comparisons.js +124 -103
- package/dist/src/{components.js → liveness/components.js} +1 -1
- package/dist/src/{graph.js → liveness/graph.js} +45 -20
- package/dist/src/liveness/matrix.js +99 -0
- package/dist/src/liveness/sweep.js +558 -0
- package/dist/src/load/expected-module.js +2 -2
- package/dist/src/load/specifiers.js +2 -4
- package/dist/src/load/synthesize.js +5 -0
- package/dist/src/load/workspace-resolution.js +2 -2
- package/dist/src/module-declarations.js +70 -85
- package/dist/src/overrides.js +134 -112
- package/dist/src/paths.js +46 -7
- package/dist/src/platform-calls.js +2 -2
- package/dist/src/platform-symbols.js +13 -19
- package/dist/src/query.js +46 -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 +237 -0
- package/dist/src/references/sources.js +450 -0
- package/dist/src/references.js +110 -1285
- package/dist/src/roots/configured-declarations.js +3 -0
- package/dist/src/roots/published-reach.js +4 -4
- package/dist/src/roots/root-set.js +1 -1
- package/dist/src/roots/unseen-loads.js +38 -10
- package/dist/src/serialization-contract.js +8 -3
- package/dist/src/stores.js +4 -2
- 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} +2 -11
- package/dist/src/type-parameter-reads.js +178 -139
- package/dist/src/unimplemented-callees.js +262 -242
- package/dist/src/verbs/analyze.js +3 -3
- package/dist/src/verbs/explain.js +75 -132
- package/dist/src/verbs/print-retained.js +3 -3
- package/jsr.json +1 -1
- package/package.json +2 -2
- package/src/alias-chain.ts +0 -7
- package/src/amd.ts +130 -0
- package/src/analysis.ts +125 -128
- package/src/augmentations.ts +42 -28
- package/src/bindings.ts +460 -0
- package/src/calls.ts +338 -46
- 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 +8 -11
- package/src/contextual-uses.ts +2 -22
- package/src/contract/config.generated.ts +4 -1
- package/src/contract/contract.generated.ts +2 -2
- package/src/contract/report.generated.ts +6 -2
- package/src/dependencies.ts +27 -28
- package/src/destructuring.ts +1 -31
- package/src/element-access.ts +188 -182
- package/src/entries/build-scripts.ts +2 -2
- package/src/entries/configuration-files.ts +11 -8
- package/src/entries/conventions.ts +2 -1
- package/src/entries/html-entries.ts +15 -14
- package/src/entries/mdx-entries.ts +2 -2
- package/src/entries/static-module.ts +2 -1
- package/src/exempt.ts +31 -46
- package/src/exposure.ts +492 -0
- package/src/facts.ts +5 -3
- package/src/finding.ts +1 -1
- package/src/findings/boundary.ts +9 -0
- package/src/findings/completion.ts +48 -23
- package/src/findings/emitter.ts +1 -1
- package/src/findings/emitters.ts +23 -41
- package/src/{implementations.ts → findings/implementations.ts} +4 -4
- package/src/{in-operands.ts → findings/in-operands.ts} +3 -3
- package/src/findings/interfaces.ts +3 -3
- package/src/findings/intra-function.ts +3 -3
- package/src/findings/reads-and-writes.ts +99 -26
- package/src/findings/unused-declarations.ts +4 -28
- package/src/findings/visibility-narrowing.ts +25 -26
- package/src/framework-lifecycle.ts +42 -14
- package/src/import-bindings.ts +98 -29
- package/src/index/sites.ts +781 -0
- package/src/indexed-access.ts +570 -527
- package/src/interface-satisfaction.ts +2 -2
- package/src/inventory.ts +19 -0
- package/src/keyof-comparisons.ts +131 -116
- package/src/{components.ts → liveness/components.ts} +3 -3
- package/src/{graph.ts → liveness/graph.ts} +93 -27
- package/src/liveness/matrix.ts +162 -0
- package/src/liveness/sweep.ts +855 -0
- package/src/load/expected-module.ts +8 -2
- package/src/load/specifiers.ts +8 -5
- package/src/load/synthesize.ts +6 -0
- package/src/load/workspace-resolution.ts +9 -2
- package/src/module-declarations.ts +74 -98
- package/src/overrides.ts +162 -134
- package/src/paths.ts +54 -8
- package/src/platform-calls.ts +3 -3
- package/src/platform-symbols.ts +11 -27
- package/src/query.ts +81 -0
- package/src/references/read-rule.ts +60 -0
- package/src/references/read-rules.ts +55 -0
- package/src/references/sink.ts +314 -0
- package/src/references/sources.ts +632 -0
- package/src/references.ts +175 -1733
- package/src/report.ts +1 -1
- package/src/roots/configured-declarations.ts +3 -0
- package/src/roots/published-reach.ts +9 -4
- package/src/roots/root-set.ts +1 -1
- package/src/roots/unseen-loads.ts +49 -11
- package/src/serialization-contract.ts +8 -3
- package/src/stores.ts +15 -3
- package/src/symbol-keys.ts +102 -102
- package/src/tests/file-class.ts +135 -0
- package/src/{outside-tests.ts → tests/outside.ts} +16 -10
- package/src/{test-support.ts → tests/support.ts} +9 -20
- package/src/type-parameter-reads.ts +187 -158
- package/src/unimplemented-callees.ts +297 -280
- package/src/verbs/analyze.ts +3 -2
- package/src/verbs/explain.ts +83 -158
- package/src/verbs/print-retained.ts +3 -3
- package/dist/src/matrix.js +0 -273
- package/dist/src/sweep.js +0 -222
- package/src/matrix.ts +0 -463
- package/src/sweep.ts +0 -361
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 {
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
import { declarationOf, membersNamed, staticModule, type Value } from "./static-module.ts";
|
|
25
25
|
import { filesNamedBy, type ParseFile } from "./configuration-files.ts";
|
|
26
26
|
import type { Host } from "../host.ts";
|
|
27
|
-
import { ancestors, dirnamePath, relativePath, resolvePath } from "../paths.ts";
|
|
27
|
+
import { ancestors, dirnamePath, isExplicitPath, relativePath, resolvePath } from "../paths.ts";
|
|
28
28
|
import type { SourceFiles } from "../source-files.ts";
|
|
29
29
|
import { bytewise } from "../text/compare.ts";
|
|
30
30
|
import { unwrapped } from "../unwrap.ts";
|
|
@@ -93,7 +93,7 @@ function lastMember(object: Value, key: string): Value | undefined {
|
|
|
93
93
|
function pathOf(value: Value, dir: string, scriptDir: string): EntryPath | undefined {
|
|
94
94
|
if (value.kind === "text") {
|
|
95
95
|
const { text } = value;
|
|
96
|
-
const request = !
|
|
96
|
+
const request = !isExplicitPath(text);
|
|
97
97
|
return { path: resolvePath(dir, text), text, request };
|
|
98
98
|
}
|
|
99
99
|
if (value.kind === "directory") {
|
|
@@ -15,7 +15,15 @@ import {
|
|
|
15
15
|
} from "@typescript/native/ast";
|
|
16
16
|
import { relativeSpecifiers } from "./static-module.ts";
|
|
17
17
|
import type { Host } from "../host.ts";
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
ancestors,
|
|
20
|
+
dirnamePath,
|
|
21
|
+
isAbsolutePath,
|
|
22
|
+
joinPath,
|
|
23
|
+
relativePath,
|
|
24
|
+
resolvePath,
|
|
25
|
+
startsRelativePath,
|
|
26
|
+
} from "../paths.ts";
|
|
19
27
|
import type { SourceFiles } from "../source-files.ts";
|
|
20
28
|
import { bytewise } from "../text/compare.ts";
|
|
21
29
|
import { isRecord } from "../json-document.ts";
|
|
@@ -50,9 +58,6 @@ const MODULE_FORMS: readonly { readonly name: RegExp; readonly form: string }[]
|
|
|
50
58
|
/** A JSON configuration file's name. */
|
|
51
59
|
const DOCUMENT_NAME = /^(?:[\w-]+(?:\.[\w-]+)?\.config\.json|\.[\w-]+rc(?:\.json)?)$/u;
|
|
52
60
|
|
|
53
|
-
/** The prefixes a string names a file with, relative to the file that writes it. */
|
|
54
|
-
const RELATIVE_PREFIXES = ["./", "../"] as const;
|
|
55
|
-
|
|
56
61
|
/** The JavaScript extensions a relative specifier from a configuration file stands for TypeScript under. */
|
|
57
62
|
const COUNTERPARTS: readonly (readonly [string, readonly string[]])[] = [
|
|
58
63
|
[".js", [".ts", ".tsx"]],
|
|
@@ -270,9 +275,7 @@ export function configurationFiles(
|
|
|
270
275
|
}
|
|
271
276
|
document.manifestDirs.push(next.manifestDir);
|
|
272
277
|
for (const text of document.strings) {
|
|
273
|
-
const path =
|
|
274
|
-
? resolvePath(dirnamePath(next.path), text)
|
|
275
|
-
: undefined;
|
|
278
|
+
const path = startsRelativePath(text) ? resolvePath(dirnamePath(next.path), text) : undefined;
|
|
276
279
|
if (
|
|
277
280
|
path?.endsWith(".json") === true &&
|
|
278
281
|
isProjectPath(root, path) &&
|
|
@@ -425,7 +428,7 @@ export function dependenciesNamed(text: string, declared: readonly string[]): re
|
|
|
425
428
|
* none.
|
|
426
429
|
*/
|
|
427
430
|
export function filesNamedBy(files: SourceFiles, dir: string, text: string): readonly SourceFile[] {
|
|
428
|
-
if (text === "" || text
|
|
431
|
+
if (text === "" || isAbsolutePath(text) || /[*?[{]/u.test(text)) {
|
|
429
432
|
return [];
|
|
430
433
|
}
|
|
431
434
|
const path = resolvePath(dir, text);
|
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
import type { Host } from "../host.ts";
|
|
43
43
|
import {
|
|
44
44
|
ancestors,
|
|
45
|
+
cannotStartPackageName,
|
|
45
46
|
dirnamePath,
|
|
46
47
|
joinPath,
|
|
47
48
|
normalizePath,
|
|
@@ -683,7 +684,7 @@ function prefixedPackage(value: string, reading: PrefixedNameReading): string |
|
|
|
683
684
|
const { prefix, marker } = reading;
|
|
684
685
|
let name: string;
|
|
685
686
|
if (marker === undefined) {
|
|
686
|
-
if (value.includes(":") ||
|
|
687
|
+
if (value.includes(":") || cannotStartPackageName(value)) {
|
|
687
688
|
return undefined;
|
|
688
689
|
}
|
|
689
690
|
const parts = value.split("/");
|
|
@@ -12,7 +12,15 @@ import {
|
|
|
12
12
|
} from "@typescript/native/ast";
|
|
13
13
|
import { resolveRelativeSpecifier, type ParseFile } from "./configuration-files.ts";
|
|
14
14
|
import type { Host } from "../host.ts";
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
ancestors,
|
|
17
|
+
dirnamePath,
|
|
18
|
+
hasURLScheme,
|
|
19
|
+
isAbsolutePath,
|
|
20
|
+
isExplicitPath,
|
|
21
|
+
joinPath,
|
|
22
|
+
resolvePath,
|
|
23
|
+
} from "../paths.ts";
|
|
16
24
|
import type { SourceFiles } from "../source-files.ts";
|
|
17
25
|
import { filesBelow } from "../fs/tree.ts";
|
|
18
26
|
import { holdsManifest } from "../fs/manifest.ts";
|
|
@@ -32,15 +40,9 @@ const SCRIPT_END = /<\/script\s*>/iu;
|
|
|
32
40
|
/** One attribute: a name, then a double-quoted, single-quoted or unquoted value. */
|
|
33
41
|
const ATTRIBUTE = /([^\s"'=<>/]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/gu;
|
|
34
42
|
|
|
35
|
-
/** A value that names a resource on another origin, or by another scheme. */
|
|
36
|
-
const ELSEWHERE = /^(?:\/\/|[A-Za-z][A-Za-z\d+.-]*:)/u;
|
|
37
|
-
|
|
38
43
|
/** The `type` values a classic script carries, compared in lowercase. */
|
|
39
44
|
const CLASSIC_TYPES: ReadonlySet<string> = new Set(["text/javascript", "application/javascript"]);
|
|
40
45
|
|
|
41
|
-
/** The prefixes an inline script's specifier names a file of the target with. */
|
|
42
|
-
const FILE_PREFIXES = ["/", "./", "../"] as const;
|
|
43
|
-
|
|
44
46
|
/** Each attribute of one start tag's attribute text, by its lowercase name. */
|
|
45
47
|
function attributes(text: string): ReadonlyMap<string, string> {
|
|
46
48
|
const found = new Map<string, string>();
|
|
@@ -94,9 +96,7 @@ function scriptValues(parse: ParseFile | undefined, path: string, text: string):
|
|
|
94
96
|
const end = rest.search(SCRIPT_END);
|
|
95
97
|
const content = end === -1 ? rest : rest.slice(0, end);
|
|
96
98
|
values.push(
|
|
97
|
-
...specifiersOf(parse, `${path}.${String(start)}.ts`, content).filter(
|
|
98
|
-
FILE_PREFIXES.some((prefix) => specifier.startsWith(prefix)),
|
|
99
|
-
),
|
|
99
|
+
...specifiersOf(parse, `${path}.${String(start)}.ts`, content).filter(isExplicitPath),
|
|
100
100
|
);
|
|
101
101
|
}
|
|
102
102
|
return values;
|
|
@@ -132,18 +132,19 @@ export function htmlEntries(
|
|
|
132
132
|
}
|
|
133
133
|
const dir = dirnamePath(path);
|
|
134
134
|
for (const value of scriptValues(parse, path, text)) {
|
|
135
|
-
|
|
135
|
+
// A value with a scheme, or one starting `//`, names a resource on another origin.
|
|
136
|
+
if (value.startsWith("//") || hasURLScheme(value)) {
|
|
136
137
|
continue;
|
|
137
138
|
}
|
|
138
|
-
const base = value
|
|
139
|
-
const relative = value
|
|
139
|
+
const base = isAbsolutePath(value) ? manifestDirectory(host, root, dir) : dir;
|
|
140
|
+
const relative = isAbsolutePath(value) ? `.${value}` : value;
|
|
140
141
|
const reached = resolveRelativeSpecifier(host, base, relative);
|
|
141
142
|
const file = reached === undefined ? undefined : files.byName.get(reached);
|
|
142
143
|
if (file !== undefined) {
|
|
143
144
|
found.push({ file, source: value });
|
|
144
145
|
continue;
|
|
145
146
|
}
|
|
146
|
-
const served = value
|
|
147
|
+
const served = isAbsolutePath(value)
|
|
147
148
|
? files.outputDirs.filter((outDir) => outDir === dir)
|
|
148
149
|
: [];
|
|
149
150
|
const emitting = [base, ...served].flatMap((against) =>
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import type { SourceFile } from "@typescript/native/ast";
|
|
8
8
|
import { resolveRelativeSpecifier } from "./configuration-files.ts";
|
|
9
9
|
import type { Host } from "../host.ts";
|
|
10
|
-
import { dirnamePath, joinPath, resolvePath } from "../paths.ts";
|
|
10
|
+
import { dirnamePath, joinPath, resolvePath, startsRelativePath } from "../paths.ts";
|
|
11
11
|
import type { SourceFiles } from "../source-files.ts";
|
|
12
12
|
import { filesBelow } from "../fs/tree.ts";
|
|
13
13
|
|
|
@@ -154,7 +154,7 @@ function importedBy(
|
|
|
154
154
|
}
|
|
155
155
|
const matched = open === undefined ? IMPORT_LINE.exec(line) : null;
|
|
156
156
|
const specifier = matched?.[2];
|
|
157
|
-
if (specifier
|
|
157
|
+
if (specifier !== undefined && startsRelativePath(specifier)) {
|
|
158
158
|
found.push({ specifier, names: clauseNames(matched?.[1] ?? "") });
|
|
159
159
|
}
|
|
160
160
|
}
|
|
@@ -62,6 +62,7 @@ import {
|
|
|
62
62
|
} from "@typescript/native/ast";
|
|
63
63
|
import { commonJSModuleValue, type ModuleValue } from "../inventory/commonjs.ts";
|
|
64
64
|
import { callsPlatformBy, lexicalBinding, writtenName, type BindingOf } from "../platform-calls.ts";
|
|
65
|
+
import { startsRelativePath } from "../paths.ts";
|
|
65
66
|
import { unwrapped } from "../unwrap.ts";
|
|
66
67
|
|
|
67
68
|
/** Where a value's text starts in its file, or undefined in a document read with no positions. */
|
|
@@ -589,7 +590,7 @@ export function relativeSpecifiers(file: SourceFile): readonly string[] {
|
|
|
589
590
|
}
|
|
590
591
|
const found: string[] = [];
|
|
591
592
|
const named = (specifier: string | undefined): void => {
|
|
592
|
-
if (specifier
|
|
593
|
+
if (specifier !== undefined && startsRelativePath(specifier)) {
|
|
593
594
|
found.push(specifier);
|
|
594
595
|
}
|
|
595
596
|
};
|