@cplieger/deadset-ts 8.0.0-dev.5 → 8.0.0-dev.7
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/bin/mapper-connection.js +2 -1
- package/dist/bin/node-host.js +3 -2
- package/dist/src/analysis.js +28 -46
- package/dist/src/automatic-types.js +10 -29
- package/dist/src/build-scripts.js +17 -29
- package/dist/src/component-layer.js +4 -2
- package/dist/src/components.js +2 -3
- package/dist/src/config.js +3 -2
- package/dist/src/configuration-files.js +27 -168
- package/dist/src/conformance-record.js +1 -1
- package/dist/src/contract/contract.generated.js +1084 -0
- package/dist/src/contract/report.generated.js +796 -0
- package/dist/src/conventions.js +20 -60
- package/dist/src/dependencies.js +25 -43
- package/dist/src/discover.js +13 -39
- package/dist/src/edges.js +7 -15
- package/dist/src/element-access.js +4 -6
- package/dist/src/entry-point-gaps.js +2 -8
- package/dist/src/entry-points.js +3 -10
- package/dist/src/enum-group.js +3 -10
- package/dist/src/erased-stores.js +4 -6
- package/dist/src/exempt-classes.js +3 -63
- package/dist/src/exempt.js +13 -40
- package/dist/src/file-facts.js +2 -25
- package/dist/src/findings/completion.js +11 -20
- package/dist/src/findings/dependencies-and-module-machinery.js +4 -5
- package/dist/src/findings/emitters.js +4 -4
- package/dist/src/findings/interfaces.js +4 -5
- package/dist/src/findings/intra-function.js +8 -7
- package/dist/src/findings/non-code-artifacts.js +5 -6
- package/dist/src/findings/reads-and-writes.js +11 -9
- package/dist/src/findings/self-check.js +10 -12
- package/dist/src/findings/unused-declarations.js +28 -27
- package/dist/src/findings/visibility-narrowing.js +9 -11
- package/dist/src/findings-pass.js +7 -14
- package/dist/src/fs/manifest.js +43 -0
- package/dist/src/fs/tree.js +88 -0
- package/dist/src/git-ignore.js +34 -25
- package/dist/src/html-entries.js +6 -33
- package/dist/src/in-operands.js +2 -1
- package/dist/src/index.js +1 -1
- package/dist/src/intra-function-parts.js +18 -26
- package/dist/src/inventory.js +2 -21
- package/dist/src/json-document.js +4 -0
- package/dist/src/keyof-comparisons.js +4 -6
- package/dist/src/kinds.js +4 -360
- package/dist/src/manifest.js +5 -43
- package/dist/src/mdx-entries.js +3 -26
- package/dist/src/partial.js +2 -1
- package/dist/src/paths.js +26 -15
- package/dist/src/position.js +2 -1
- package/dist/src/print.js +3 -2
- package/dist/src/product.js +13 -0
- package/dist/src/references.js +14 -27
- package/dist/src/report-schema.js +272 -0
- package/dist/src/report.js +39 -42
- package/dist/src/reporters/sarif.js +4 -2
- package/dist/src/reporters/template.js +4 -19
- package/dist/src/resolve.js +12 -26
- package/dist/src/roots.js +7 -17
- package/dist/src/run.js +10 -8
- package/dist/src/schema.js +4 -3
- package/dist/src/scope.js +4 -5
- package/dist/src/serialization-contract.js +4 -8
- package/dist/src/session.js +2 -1
- package/dist/src/setup-failure.js +2 -6
- package/dist/src/suppress-file.js +12 -13
- package/dist/src/suppress-inline.js +3 -2
- package/dist/src/suppress.js +29 -48
- package/dist/src/symbol-keys.js +3 -5
- package/dist/src/template-field.js +5 -15
- package/dist/src/test-globals.js +6 -28
- package/dist/src/test-joins.js +6 -6
- package/dist/src/text/compare.js +26 -0
- package/dist/src/text/glob.js +194 -0
- package/dist/src/text/shell.js +159 -0
- package/dist/src/{yaml-document.js → text/yaml.js} +38 -0
- package/dist/src/type-errors.js +14 -38
- package/dist/src/unseen-loads.js +2 -9
- package/dist/src/unwrap.js +23 -0
- package/dist/src/verbs/analyze.js +22 -15
- package/dist/src/verbs/describe.js +7 -7
- package/dist/src/verbs/explain.js +7 -4
- package/dist/src/verbs/print-config.js +2 -1
- package/dist/src/verbs/print-projects.js +4 -2
- package/dist/src/verbs/print-retained.js +4 -2
- package/dist/src/verbs/print-roots.js +4 -2
- package/dist/src/verbs/verb.js +1 -5
- package/dist/src/verbs/version.js +4 -3
- package/dist/src/workflow-steps.js +9 -46
- package/dist/src/workspace-manifests.js +2 -2
- package/dist/src/workspace-programs.js +5 -3
- package/dist/src/workspace-resolution.js +13 -17
- package/dist/src/workspace.js +28 -116
- package/jsr.json +1 -1
- package/package.json +2 -1
- package/src/analysis.ts +29 -54
- package/src/automatic-types.ts +11 -29
- package/src/build-scripts.ts +17 -38
- package/src/component-layer.ts +4 -2
- package/src/components.ts +2 -4
- package/src/config.ts +11 -15
- package/src/configuration-files.ts +27 -170
- package/src/conformance-record.ts +1 -1
- package/src/contract/contract.generated.ts +1148 -0
- package/src/contract/report.generated.ts +1157 -0
- package/src/conventions.ts +26 -74
- package/src/dependencies.ts +32 -50
- package/src/discover.ts +14 -39
- package/src/edges.ts +7 -21
- package/src/element-access.ts +4 -7
- package/src/entry-point-gaps.ts +3 -9
- package/src/entry-points.ts +2 -13
- package/src/enum-group.ts +2 -11
- package/src/erased-stores.ts +3 -7
- package/src/exempt-classes.ts +5 -74
- package/src/exempt.ts +17 -47
- package/src/file-facts.ts +6 -24
- package/src/finding.ts +9 -9
- package/src/findings/completion.ts +22 -23
- package/src/findings/dependencies-and-module-machinery.ts +4 -7
- package/src/findings/emitter.ts +6 -7
- package/src/findings/emitters.ts +6 -6
- package/src/findings/interfaces.ts +4 -6
- package/src/findings/intra-function.ts +8 -8
- package/src/findings/non-code-artifacts.ts +5 -7
- package/src/findings/reads-and-writes.ts +15 -12
- package/src/findings/self-check.ts +11 -17
- package/src/findings/unused-declarations.ts +28 -27
- package/src/findings/visibility-narrowing.ts +9 -12
- package/src/findings-pass.ts +7 -16
- package/src/fs/manifest.ts +52 -0
- package/src/fs/tree.ts +110 -0
- package/src/git-ignore.ts +38 -25
- package/src/html-entries.ts +6 -33
- package/src/in-operands.ts +2 -1
- package/src/index.ts +1 -1
- package/src/intra-function-parts.ts +18 -28
- package/src/inventory.ts +2 -20
- package/src/json-document.ts +5 -0
- package/src/keyof-comparisons.ts +3 -7
- package/src/kinds.ts +6 -406
- package/src/manifest.ts +5 -46
- package/src/mdx-entries.ts +3 -26
- package/src/partial.ts +2 -1
- package/src/paths.ts +27 -15
- package/src/position.ts +2 -1
- package/src/print.ts +3 -2
- package/src/product.ts +18 -0
- package/src/references.ts +14 -29
- package/src/report-schema.ts +364 -0
- package/src/report.ts +66 -229
- package/src/reporters/annotations.ts +2 -2
- package/src/reporters/json.ts +1 -1
- package/src/reporters/reporter.ts +2 -2
- package/src/reporters/reporters.ts +1 -1
- package/src/reporters/sarif.ts +17 -12
- package/src/reporters/template.ts +4 -20
- package/src/reporters/text.ts +3 -3
- package/src/resolve.ts +31 -38
- package/src/roots.ts +7 -20
- package/src/run.ts +10 -14
- package/src/schema.ts +4 -3
- package/src/scope.ts +4 -10
- package/src/serialization-contract.ts +4 -9
- package/src/session.ts +2 -1
- package/src/setup-failure.ts +5 -7
- package/src/suppress-file.ts +11 -15
- package/src/suppress-inline.ts +2 -2
- package/src/suppress.ts +39 -55
- package/src/symbol-keys.ts +2 -5
- package/src/template-field.ts +5 -18
- package/src/test-globals.ts +9 -27
- package/src/test-joins.ts +6 -8
- package/src/text/compare.ts +27 -0
- package/src/text/glob.ts +210 -0
- package/src/text/shell.ts +161 -0
- package/src/{yaml-document.ts → text/yaml.ts} +46 -0
- package/src/type-errors.ts +25 -36
- package/src/unseen-loads.ts +1 -12
- package/src/unwrap.ts +34 -0
- package/src/verbs/analyze.ts +38 -25
- package/src/verbs/describe.ts +13 -7
- package/src/verbs/explain.ts +7 -4
- package/src/verbs/print-config.ts +2 -1
- package/src/verbs/print-projects.ts +4 -2
- package/src/verbs/print-retained.ts +4 -2
- package/src/verbs/print-roots.ts +4 -2
- package/src/verbs/verb.ts +0 -6
- package/src/verbs/version.ts +4 -3
- package/src/workflow-steps.ts +9 -44
- package/src/workspace-manifests.ts +2 -2
- package/src/workspace-programs.ts +5 -3
- package/src/workspace-resolution.ts +21 -17
- package/src/workspace.ts +35 -121
- package/dist/src/glob.js +0 -65
- package/dist/src/pnpm-workspace.js +0 -120
- package/dist/src/version.js +0 -7
- package/src/glob.ts +0 -67
- package/src/pnpm-workspace.ts +0 -135
- package/src/version.ts +0 -7
package/dist/src/conventions.js
CHANGED
|
@@ -5,14 +5,19 @@
|
|
|
5
5
|
* directory a configuration property moves read from the property's literal value.
|
|
6
6
|
* No configuration file is run.
|
|
7
7
|
*/
|
|
8
|
-
import { isArrayLiteralExpression,
|
|
8
|
+
import { isArrayLiteralExpression, isBinaryExpression, isCallExpression, isClassDeclaration, isComputedPropertyName, isExportAssignment, isExportDeclaration, isExpressionStatement, isFunctionDeclaration, isIdentifier, isImportDeclaration, isNamedExports, isNamespaceImport, isNoSubstitutionTemplateLiteral, isNumericLiteral, isObjectBindingPattern, isObjectLiteralExpression, isPropertyAccessExpression, isPropertyAssignment, isShorthandPropertyAssignment, isSpreadAssignment, isStringLiteral, isVariableStatement, SyntaxKind, } from "@typescript/native/ast";
|
|
9
9
|
import { lineOf } from "./component-files.js";
|
|
10
10
|
import { CONVENTION_ROWS, } from "./convention-rows.js";
|
|
11
11
|
import { documentStrings } from "./configuration-files.js";
|
|
12
|
-
import {
|
|
13
|
-
import { dirnamePath, joinPath, normalizePath, relativePath, resolvePath } from "./paths.js";
|
|
12
|
+
import { ancestors, dirnamePath, joinPath, normalizePath, relativePath, resolvePath, } from "./paths.js";
|
|
14
13
|
import { satisfies } from "./version-range.js";
|
|
15
|
-
import {
|
|
14
|
+
import { bytewise } from "./text/compare.js";
|
|
15
|
+
import { isRecord } from "./json-document.js";
|
|
16
|
+
import { unwrapped } from "./unwrap.js";
|
|
17
|
+
import { filesIn } from "./fs/tree.js";
|
|
18
|
+
import { INSTALLED_PACKAGES, MANIFEST, readJSON } from "./fs/manifest.js";
|
|
19
|
+
import { globExpression } from "./text/glob.js";
|
|
20
|
+
import { yamlDocument } from "./text/yaml.js";
|
|
16
21
|
const JSON_EXTENSION = ".json";
|
|
17
22
|
/**
|
|
18
23
|
* A configuration file its tool reads as a YAML document, read as the JSON document it
|
|
@@ -29,17 +34,6 @@ const DEPENDENCY_SECTIONS = [
|
|
|
29
34
|
"peerDependencies",
|
|
30
35
|
"optionalDependencies",
|
|
31
36
|
];
|
|
32
|
-
function isRecord(value) {
|
|
33
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
34
|
-
}
|
|
35
|
-
function readJSON(host, path) {
|
|
36
|
-
try {
|
|
37
|
-
return JSON.parse(host.readFile(path));
|
|
38
|
-
}
|
|
39
|
-
catch {
|
|
40
|
-
return undefined;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
37
|
function declares(manifest, name, sections = DEPENDENCY_SECTIONS) {
|
|
44
38
|
if (!isRecord(manifest)) {
|
|
45
39
|
return false;
|
|
@@ -55,32 +49,15 @@ function declares(manifest, name, sections = DEPENDENCY_SECTIONS) {
|
|
|
55
49
|
* none, or `undefined` where no `node_modules` holds it.
|
|
56
50
|
*/
|
|
57
51
|
function installedVersion(host, dir, name) {
|
|
58
|
-
for (
|
|
59
|
-
const path = joinPath(at,
|
|
52
|
+
for (const at of ancestors(dir)) {
|
|
53
|
+
const path = joinPath(at, INSTALLED_PACKAGES, name, MANIFEST);
|
|
60
54
|
if (host.kindOf(path) === "file") {
|
|
61
55
|
const manifest = readJSON(host, path);
|
|
62
56
|
const version = isRecord(manifest) ? manifest["version"] : undefined;
|
|
63
57
|
return typeof version === "string" ? version : "";
|
|
64
58
|
}
|
|
65
|
-
if (dirnamePath(at) === at) {
|
|
66
|
-
return undefined;
|
|
67
|
-
}
|
|
68
59
|
}
|
|
69
|
-
|
|
70
|
-
/** Whether one node wraps an expression without changing its value. */
|
|
71
|
-
function isWrapper(node) {
|
|
72
|
-
return (isParenthesizedExpression(node) ||
|
|
73
|
-
isAsExpression(node) ||
|
|
74
|
-
isSatisfiesExpression(node) ||
|
|
75
|
-
isNonNullExpression(node));
|
|
76
|
-
}
|
|
77
|
-
/** The expression a wrapper that changes no value holds. */
|
|
78
|
-
function unwrapped(node) {
|
|
79
|
-
let at = node;
|
|
80
|
-
while (isWrapper(at)) {
|
|
81
|
-
at = at.expression;
|
|
82
|
-
}
|
|
83
|
-
return at;
|
|
60
|
+
return undefined;
|
|
84
61
|
}
|
|
85
62
|
/** The key one property is written with, where it is written as a name or as literal text. */
|
|
86
63
|
function keyOf(property) {
|
|
@@ -569,17 +546,7 @@ function expand(template, resolved) {
|
|
|
569
546
|
/** The configuration files in one directory that one glob names, by name. */
|
|
570
547
|
function configurationFiles(host, dir, glob) {
|
|
571
548
|
const expression = globExpression(glob);
|
|
572
|
-
|
|
573
|
-
try {
|
|
574
|
-
entries = host.readDirectory(dir);
|
|
575
|
-
}
|
|
576
|
-
catch {
|
|
577
|
-
return [];
|
|
578
|
-
}
|
|
579
|
-
return entries
|
|
580
|
-
.filter((entry) => !entry.directory && expression.test(entry.name))
|
|
581
|
-
.map((entry) => entry.name)
|
|
582
|
-
.sort();
|
|
549
|
+
return filesIn(host, dir, (name) => expression.test(name));
|
|
583
550
|
}
|
|
584
551
|
function resolveMove(host, parse, dir, row, move, resolved) {
|
|
585
552
|
const set = [];
|
|
@@ -667,7 +634,7 @@ function shortNameUses(host, parse, dir, manifest, readings) {
|
|
|
667
634
|
}
|
|
668
635
|
}
|
|
669
636
|
}
|
|
670
|
-
return [...used].filter((name) => declared.has(name)).sort(
|
|
637
|
+
return [...used].filter((name) => declared.has(name)).sort(bytewise);
|
|
671
638
|
}
|
|
672
639
|
/**
|
|
673
640
|
* The package one value of a prefixed-name reading names, or none: ESLint's own naming,
|
|
@@ -718,7 +685,7 @@ function prefixedNameUses(host, parse, dir, manifest, readings) {
|
|
|
718
685
|
}
|
|
719
686
|
}
|
|
720
687
|
}
|
|
721
|
-
return [...used].sort(
|
|
688
|
+
return [...used].sort(bytewise);
|
|
722
689
|
}
|
|
723
690
|
/** The declared dependencies an applied row's helper settings use. */
|
|
724
691
|
function helperUses(host, parse, dir, manifest, readings) {
|
|
@@ -775,13 +742,6 @@ function packageKeyUses(host, parse, dir, manifest, keys) {
|
|
|
775
742
|
text.startsWith(`${name}/`) ||
|
|
776
743
|
(text.startsWith(`${name}:`) && text.length > name.length + 1)));
|
|
777
744
|
}
|
|
778
|
-
/** Two strings ordered bytewise. */
|
|
779
|
-
function compare(a, b) {
|
|
780
|
-
if (a === b) {
|
|
781
|
-
return 0;
|
|
782
|
-
}
|
|
783
|
-
return a < b ? -1 : 1;
|
|
784
|
-
}
|
|
785
745
|
/**
|
|
786
746
|
* What the rows decide over the manifests the analysis reads. A row `disabled` names
|
|
787
747
|
* is skipped before anything is read for it.
|
|
@@ -795,7 +755,7 @@ export function readConventions(host, parse, manifests, disabled, rows = CONVENT
|
|
|
795
755
|
const selected = new Map();
|
|
796
756
|
const testFiles = new Set();
|
|
797
757
|
for (const manifest of manifests) {
|
|
798
|
-
const declared = readJSON(host, joinPath(manifest.dir,
|
|
758
|
+
const declared = readJSON(host, joinPath(manifest.dir, MANIFEST));
|
|
799
759
|
const versions = new Map();
|
|
800
760
|
const missing = new Set();
|
|
801
761
|
for (const row of rows) {
|
|
@@ -893,15 +853,15 @@ export function readConventions(host, parse, manifests, disabled, rows = CONVENT
|
|
|
893
853
|
}
|
|
894
854
|
}
|
|
895
855
|
const unique = [...new Map(applied.map((one) => [JSON.stringify(one), one])).values()];
|
|
896
|
-
unique.sort((a, b) =>
|
|
897
|
-
|
|
898
|
-
|
|
856
|
+
unique.sort((a, b) => bytewise(a.name, b.name) ||
|
|
857
|
+
bytewise(a.manifest, b.manifest) ||
|
|
858
|
+
bytewise(JSON.stringify(a), JSON.stringify(b)));
|
|
899
859
|
return {
|
|
900
860
|
applied: unique,
|
|
901
861
|
globs,
|
|
902
862
|
generated,
|
|
903
863
|
failures,
|
|
904
|
-
uses: [...uses].sort(
|
|
864
|
+
uses: [...uses].sort(bytewise),
|
|
905
865
|
selected,
|
|
906
866
|
testFiles,
|
|
907
867
|
};
|
package/dist/src/dependencies.js
CHANGED
|
@@ -10,14 +10,15 @@ import { isArrayLiteralExpression, isCallExpression, isExportDeclaration, isExpr
|
|
|
10
10
|
import { automaticTypes } from "./automatic-types.js";
|
|
11
11
|
import { configurationFiles, declaredIn as declaredBeside, dependenciesNamed, moduleStrings, outsideChain, } from "./configuration-files.js";
|
|
12
12
|
import { nodeKey, packageScope } from "./inventory.js";
|
|
13
|
-
import {
|
|
14
|
-
import { dirnamePath, isAbsolutePath, joinPath, relativePath, resolvePath } from "./paths.js";
|
|
13
|
+
import { ancestors, dirnamePath, isAbsolutePath, joinPath, relativePath, resolvePath, } from "./paths.js";
|
|
15
14
|
import { UNANSWERED } from "./query.js";
|
|
16
15
|
import { sourceFilesOf } from "./source-files.js";
|
|
17
16
|
import { workflowCommands, workflowTokens } from "./workflow-steps.js";
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
import { bytewise } from "./text/compare.js";
|
|
18
|
+
import { isRecord } from "./json-document.js";
|
|
19
|
+
import { inInstalledPackages, INSTALLED_PACKAGES, MANIFEST, readDocument } from "./fs/manifest.js";
|
|
20
|
+
import { commandsOf, scriptTokens } from "./text/shell.js";
|
|
21
|
+
const MODULES_SEGMENT = `/${INSTALLED_PACKAGES}/`;
|
|
21
22
|
const TYPES_SCOPE = "@types/";
|
|
22
23
|
/** A script token naming a JavaScript file by a path no expansion changes. */
|
|
23
24
|
const SCRIPT_FILE = /^[^$`{*?[~]+\.(?:js|mjs|cjs)$/u;
|
|
@@ -39,25 +40,6 @@ export function configurationNeeds(packages) {
|
|
|
39
40
|
}
|
|
40
41
|
/** The key of {@link ProjectNeeds.at} for a use no file of the target governs. */
|
|
41
42
|
const ANYWHERE = "";
|
|
42
|
-
function isRecord(value) {
|
|
43
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
44
|
-
}
|
|
45
|
-
/** One JSON document's decoded value, or undefined where it cannot be read or parsed. */
|
|
46
|
-
function readJSON(host, path) {
|
|
47
|
-
let text;
|
|
48
|
-
try {
|
|
49
|
-
text = host.readFile(path);
|
|
50
|
-
}
|
|
51
|
-
catch {
|
|
52
|
-
return undefined;
|
|
53
|
-
}
|
|
54
|
-
try {
|
|
55
|
-
return { text, value: JSON.parse(text) };
|
|
56
|
-
}
|
|
57
|
-
catch {
|
|
58
|
-
return undefined;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
43
|
/**
|
|
62
44
|
* The package a bare module specifier names: its first segment, or its first two
|
|
63
45
|
* where it starts with a scope. A relative, absolute or scheme-prefixed specifier and
|
|
@@ -280,7 +262,7 @@ export function projectNeeds(project, held, host, targetRoot, parse) {
|
|
|
280
262
|
}
|
|
281
263
|
for (const { strings, manifestDirs } of configuration.documents) {
|
|
282
264
|
for (const manifestDir of manifestDirs) {
|
|
283
|
-
const names = declaredAt(joinPath(manifestDir,
|
|
265
|
+
const names = declaredAt(joinPath(manifestDir, MANIFEST));
|
|
284
266
|
for (const text of strings) {
|
|
285
267
|
use([PROJECT_OWNER], dependenciesNamed(text, names), joinPath(manifestDir, MANIFEST));
|
|
286
268
|
}
|
|
@@ -289,7 +271,7 @@ export function projectNeeds(project, held, host, targetRoot, parse) {
|
|
|
289
271
|
const ranFiles = outsideChain(host, targetRoot, files, parse, scriptRunFiles(host, targetRoot, files));
|
|
290
272
|
for (const { file, manifestDirs } of [...configuration.outside, ...ranFiles]) {
|
|
291
273
|
for (const manifestDir of manifestDirs) {
|
|
292
|
-
const names = declaredAt(joinPath(manifestDir,
|
|
274
|
+
const names = declaredAt(joinPath(manifestDir, MANIFEST));
|
|
293
275
|
for (const { text } of moduleStrings(file)) {
|
|
294
276
|
use([PROJECT_OWNER], dependenciesNamed(text, names), joinPath(manifestDir, MANIFEST));
|
|
295
277
|
}
|
|
@@ -307,8 +289,8 @@ function scriptRunFiles(host, targetRoot, files) {
|
|
|
307
289
|
const root = resolvePath(host.workingDirectory(), targetRoot);
|
|
308
290
|
const dirs = new Set([root]);
|
|
309
291
|
for (const name of files.byName.keys()) {
|
|
310
|
-
for (
|
|
311
|
-
if (
|
|
292
|
+
for (const dir of ancestors(dirnamePath(name), root)) {
|
|
293
|
+
if (dirs.has(dir)) {
|
|
312
294
|
break;
|
|
313
295
|
}
|
|
314
296
|
dirs.add(dir);
|
|
@@ -318,7 +300,7 @@ function scriptRunFiles(host, targetRoot, files) {
|
|
|
318
300
|
[root, new Set(workflowTokens(host, root))],
|
|
319
301
|
]);
|
|
320
302
|
for (const dir of dirs) {
|
|
321
|
-
const read =
|
|
303
|
+
const read = readDocument(host, joinPath(dir, MANIFEST));
|
|
322
304
|
if (read !== undefined && isRecord(read.value)) {
|
|
323
305
|
const own = scriptTokensOf(read.value);
|
|
324
306
|
tokens.set(dir, dir === root ? new Set([...own, ...(tokens.get(root) ?? [])]) : own);
|
|
@@ -330,7 +312,8 @@ function scriptRunFiles(host, targetRoot, files) {
|
|
|
330
312
|
const path = SCRIPT_FILE.test(token) ? resolvePath(manifestDir, token) : undefined;
|
|
331
313
|
const below = path === undefined ? undefined : relativePath(root, path);
|
|
332
314
|
if (path !== undefined &&
|
|
333
|
-
below
|
|
315
|
+
below !== undefined &&
|
|
316
|
+
!inInstalledPackages(below) &&
|
|
334
317
|
!files.byName.has(path) &&
|
|
335
318
|
host.kindOf(path) === "file") {
|
|
336
319
|
found.push({ path, manifestDir });
|
|
@@ -600,8 +583,8 @@ function lineAndColumn(text, offset) {
|
|
|
600
583
|
}
|
|
601
584
|
/** The installed copy of one dependency, read where the package manager puts it for the target. */
|
|
602
585
|
function installedOf(host, root, name) {
|
|
603
|
-
for (
|
|
604
|
-
const read =
|
|
586
|
+
for (const dir of ancestors(root)) {
|
|
587
|
+
const read = readDocument(host, joinPath(dir, INSTALLED_PACKAGES, name, MANIFEST));
|
|
605
588
|
if (read !== undefined && isRecord(read.value)) {
|
|
606
589
|
const bin = read.value["bin"];
|
|
607
590
|
const peers = read.value["peerDependencies"];
|
|
@@ -617,10 +600,8 @@ function installedOf(host, root, name) {
|
|
|
617
600
|
: [],
|
|
618
601
|
};
|
|
619
602
|
}
|
|
620
|
-
if (dirnamePath(dir) === dir) {
|
|
621
|
-
return undefined;
|
|
622
|
-
}
|
|
623
603
|
}
|
|
604
|
+
return undefined;
|
|
624
605
|
}
|
|
625
606
|
/** Every dependency the manifest text at `path` declares, in the order the text writes them. */
|
|
626
607
|
function declaredIn(text, manifest, path, scope) {
|
|
@@ -694,8 +675,6 @@ const PRELOADING_PROGRAMS = new Set([
|
|
|
694
675
|
/** The programs that run the command after them, and an environment assignment before it. */
|
|
695
676
|
const LAUNCHERS = new Set(["cross-env", "env", "npx"]);
|
|
696
677
|
const ASSIGNMENT = /^[A-Za-z_][A-Za-z0-9_]*=/u;
|
|
697
|
-
/** The commands one script string runs, split at the shell's list and pipeline operators. */
|
|
698
|
-
const COMMAND_SEPARATORS = /&&|\|\||;|\||&/u;
|
|
699
678
|
/**
|
|
700
679
|
* The command strings one manifest runs: each of its `scripts`, and the `exec` command of
|
|
701
680
|
* nodemon's configuration, in the manifest's `nodemonConfig` or the `nodemon.json` beside
|
|
@@ -704,7 +683,10 @@ const COMMAND_SEPARATORS = /&&|\|\||;|\||&/u;
|
|
|
704
683
|
*/
|
|
705
684
|
function manifestCommands(host, dir, manifest) {
|
|
706
685
|
const scripts = manifest["scripts"];
|
|
707
|
-
const nodemon = [
|
|
686
|
+
const nodemon = [
|
|
687
|
+
manifest["nodemonConfig"],
|
|
688
|
+
readDocument(host, joinPath(dir, "nodemon.json"))?.value,
|
|
689
|
+
];
|
|
708
690
|
return [
|
|
709
691
|
...(isRecord(scripts) ? Object.values(scripts) : []),
|
|
710
692
|
...nodemon.map((config) => (isRecord(config) ? config["exec"] : undefined)),
|
|
@@ -718,7 +700,7 @@ function manifestCommands(host, dir, manifest) {
|
|
|
718
700
|
function preloadsOf(scripts) {
|
|
719
701
|
const found = new Set();
|
|
720
702
|
for (const script of scripts) {
|
|
721
|
-
for (const command of script
|
|
703
|
+
for (const command of commandsOf(script)) {
|
|
722
704
|
const tokens = scriptTokens(command);
|
|
723
705
|
let at = 0;
|
|
724
706
|
while (at < tokens.length &&
|
|
@@ -833,7 +815,7 @@ export function dependenciesOf(host, targetRoot, perProject, candidates, members
|
|
|
833
815
|
const peers = new Map();
|
|
834
816
|
const uninstalledHere = new Set(nested);
|
|
835
817
|
for (const [dir, path] of manifests) {
|
|
836
|
-
const read =
|
|
818
|
+
const read = readDocument(host, joinPath(dir, MANIFEST));
|
|
837
819
|
if (read === undefined || !isRecord(read.value)) {
|
|
838
820
|
continue;
|
|
839
821
|
}
|
|
@@ -909,7 +891,7 @@ export function dependenciesOf(host, targetRoot, perProject, candidates, members
|
|
|
909
891
|
const heldBy = new Map();
|
|
910
892
|
for (const [key, held] of holders) {
|
|
911
893
|
if (!live.has(key) && !ran.has(key)) {
|
|
912
|
-
heldBy.set(key, [...held].sort(
|
|
894
|
+
heldBy.set(key, [...held].sort(bytewise));
|
|
913
895
|
}
|
|
914
896
|
}
|
|
915
897
|
const users = new Map();
|
|
@@ -921,7 +903,7 @@ export function dependenciesOf(host, targetRoot, perProject, candidates, members
|
|
|
921
903
|
for (const id of candidates) {
|
|
922
904
|
const sole = [...(uses.get(id) ?? [])].filter((one) => users.get(one) === 1 && names.has(one));
|
|
923
905
|
if (sole.length > 0) {
|
|
924
|
-
lastUses.set(id, sole.sort(
|
|
906
|
+
lastUses.set(id, sole.sort(bytewise));
|
|
925
907
|
}
|
|
926
908
|
}
|
|
927
909
|
const owners = new Map();
|
|
@@ -933,7 +915,7 @@ export function dependenciesOf(host, targetRoot, perProject, candidates, members
|
|
|
933
915
|
}
|
|
934
916
|
}
|
|
935
917
|
const fileLastUses = new Map();
|
|
936
|
-
for (const [one, held] of [...owners].sort(([a], [b]) => (a
|
|
918
|
+
for (const [one, held] of [...owners].sort(([a], [b]) => bytewise(a, b))) {
|
|
937
919
|
const paths = new Set([...held].map((owner) => owner.replace(/:\d+:\d+$/u, "")));
|
|
938
920
|
const [path] = paths;
|
|
939
921
|
if (paths.size === 1 && path !== undefined && path !== PROJECT_OWNER) {
|
package/dist/src/discover.js
CHANGED
|
@@ -3,10 +3,15 @@ import { baseUrlPaths } from "./base-url.js";
|
|
|
3
3
|
import { dirnamePath, joinPath, relativePath, resolvePath } from "./paths.js";
|
|
4
4
|
import { SetupError } from "./setup-failure.js";
|
|
5
5
|
import { writtenPath } from "./workspace-programs.js";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
import { filesBelow } from "./fs/tree.js";
|
|
7
|
+
import { LANGUAGE, message } from "./product.js";
|
|
8
|
+
import { LANGUAGE_ROWS } from "./contract/contract.generated.js";
|
|
9
|
+
import { globExpression } from "./text/glob.js";
|
|
10
|
+
const MARKERS = LANGUAGE_ROWS[LANGUAGE].markers.map(globExpression);
|
|
11
|
+
/** Whether one file name is a compiler configuration's: one of the language row's markers. */
|
|
12
|
+
export function isConfigFile(name) {
|
|
13
|
+
return MARKERS.some((marker) => marker.test(name));
|
|
14
|
+
}
|
|
10
15
|
/**
|
|
11
16
|
* A run that cannot read what it was asked to analyze. It ends the run with the
|
|
12
17
|
* failure code and no finding list: a configuration file the compiler cannot read,
|
|
@@ -111,40 +116,9 @@ export function targetRelative(text, targetRoot) {
|
|
|
111
116
|
export function isGuess(discovery, configFile) {
|
|
112
117
|
return discovery.derived && !discovery.fromScope.includes(configFile);
|
|
113
118
|
}
|
|
114
|
-
/**
|
|
115
|
-
* The configuration files below `root`, in ascending path order, skipping an
|
|
116
|
-
* ignored directory. A directory that cannot be read is skipped: a tree the
|
|
117
|
-
* analysis may not enter names no project.
|
|
118
|
-
*/
|
|
119
|
+
/** The configuration files below `root`, by absolute path in ascending order. */
|
|
119
120
|
function configFilesUnder(host, root) {
|
|
120
|
-
|
|
121
|
-
const pending = [root];
|
|
122
|
-
while (pending.length > 0) {
|
|
123
|
-
const dir = pending.pop();
|
|
124
|
-
if (dir === undefined) {
|
|
125
|
-
break;
|
|
126
|
-
}
|
|
127
|
-
let entries;
|
|
128
|
-
try {
|
|
129
|
-
entries = host.readDirectory(dir);
|
|
130
|
-
}
|
|
131
|
-
catch {
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
for (const entry of [...entries].sort((a, b) => (a.name < b.name ? -1 : 1))) {
|
|
135
|
-
const path = joinPath(dir, entry.name);
|
|
136
|
-
if (entry.directory) {
|
|
137
|
-
if (!IGNORED_DIRECTORIES.has(entry.name)) {
|
|
138
|
-
pending.push(path);
|
|
139
|
-
}
|
|
140
|
-
continue;
|
|
141
|
-
}
|
|
142
|
-
if (CONFIG_FILE.test(entry.name)) {
|
|
143
|
-
found.push(path);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
return found.sort();
|
|
121
|
+
return filesBelow(host, root, isConfigFile).map((path) => joinPath(root, path));
|
|
148
122
|
}
|
|
149
123
|
/**
|
|
150
124
|
* The configuration file the scope names for the target directly, where its path
|
|
@@ -211,7 +185,7 @@ export function consumerProjects(engine, host, root) {
|
|
|
211
185
|
if (kind !== "directory") {
|
|
212
186
|
throw new DiscoveryError(`the consumer ${root} is not a directory`, []);
|
|
213
187
|
}
|
|
214
|
-
const found = derivedFrom(engine, host, configFilesUnder(host, root), () => true);
|
|
188
|
+
const found = derivedFrom(engine, host, [...configFilesUnder(host, root)], () => true);
|
|
215
189
|
if (found.length === 0) {
|
|
216
190
|
throw new DiscoveryError(`the consumer ${root} holds no compiler configuration, so none of its references can be read`, []);
|
|
217
191
|
}
|
|
@@ -253,7 +227,7 @@ function readConfiguration(engine, configFile) {
|
|
|
253
227
|
: { reason: `TS${String(circular.code)}: ${circular.text.replace("{0}", () => configFile)}` };
|
|
254
228
|
}
|
|
255
229
|
catch (error) {
|
|
256
|
-
return { reason:
|
|
230
|
+
return { reason: message(error) };
|
|
257
231
|
}
|
|
258
232
|
}
|
|
259
233
|
/**
|
package/dist/src/edges.js
CHANGED
|
@@ -5,10 +5,12 @@
|
|
|
5
5
|
* pairing is a use, and the merge reads the two evaluations together.
|
|
6
6
|
*/
|
|
7
7
|
import { ConfigError } from "./config.js";
|
|
8
|
-
import { positionAt, walkDocument } from "./json-document.js";
|
|
8
|
+
import { isRecord, positionAt, walkDocument } from "./json-document.js";
|
|
9
9
|
import { joinPath } from "./paths.js";
|
|
10
10
|
import { positionKey } from "./position.js";
|
|
11
11
|
import { isPartSubject } from "./suppress.js";
|
|
12
|
+
import { bytewise } from "./text/compare.js";
|
|
13
|
+
import { message } from "./product.js";
|
|
12
14
|
/** The name and the location the Contract fixes for the edges document. */
|
|
13
15
|
export const EDGES_FILE = "deadset-edges.json";
|
|
14
16
|
/** The language prefix of every reference this analyzer evaluates. */
|
|
@@ -64,15 +66,12 @@ function carriesWildcard(ref) {
|
|
|
64
66
|
}
|
|
65
67
|
return false;
|
|
66
68
|
}
|
|
67
|
-
function isObject(value) {
|
|
68
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
69
|
-
}
|
|
70
69
|
/** One edge, checked: the closed key list, the value types and the value forms. */
|
|
71
70
|
function readEdge(value, at) {
|
|
72
71
|
const refuse = (text, want) => {
|
|
73
72
|
throw new EdgesError(at, text, want);
|
|
74
73
|
};
|
|
75
|
-
if (!
|
|
74
|
+
if (!isRecord(value)) {
|
|
76
75
|
return refuse(JSON.stringify(value), EDGE_WANT);
|
|
77
76
|
}
|
|
78
77
|
for (const [key, held] of Object.entries(value)) {
|
|
@@ -111,9 +110,9 @@ export function readEdgeSides(host, targetRoot) {
|
|
|
111
110
|
parsed = JSON.parse(text);
|
|
112
111
|
}
|
|
113
112
|
catch (error) {
|
|
114
|
-
throw new EdgesError(EDGES_FILE,
|
|
113
|
+
throw new EdgesError(EDGES_FILE, message(error), DOCUMENT_WANT);
|
|
115
114
|
}
|
|
116
|
-
if (!
|
|
115
|
+
if (!isRecord(parsed)) {
|
|
117
116
|
throw new EdgesError(EDGES_FILE, JSON.stringify(parsed), DOCUMENT_WANT);
|
|
118
117
|
}
|
|
119
118
|
const walk = walkDocument(text, "edges");
|
|
@@ -145,13 +144,6 @@ export function readEdgeSides(host, targetRoot) {
|
|
|
145
144
|
});
|
|
146
145
|
return sides;
|
|
147
146
|
}
|
|
148
|
-
/** Two strings ordered bytewise. */
|
|
149
|
-
function compare(a, b) {
|
|
150
|
-
if (a === b) {
|
|
151
|
-
return 0;
|
|
152
|
-
}
|
|
153
|
-
return a < b ? -1 : 1;
|
|
154
|
-
}
|
|
155
147
|
/**
|
|
156
148
|
* Evaluates every declared side of this language over the run's findings. A side naming a
|
|
157
149
|
* symbol the run enumerates nothing under is `absent`; otherwise it is evaluated once per
|
|
@@ -191,6 +183,6 @@ export function evaluateEdges(findings, sides, symbols) {
|
|
|
191
183
|
return { ...side, state: "dead", finding };
|
|
192
184
|
});
|
|
193
185
|
});
|
|
194
|
-
evaluations.sort((a, b) =>
|
|
186
|
+
evaluations.sort((a, b) => bytewise(a.edge, b.edge) || bytewise(a.side, b.side));
|
|
195
187
|
return { findings: findings.filter((_finding, at) => !pending.has(at)), evaluations };
|
|
196
188
|
}
|
|
@@ -8,6 +8,7 @@ import { isArrayLiteralExpression, isArrowFunction, isBinaryExpression, isCallEx
|
|
|
8
8
|
import { nodeKey } from "./inventory.js";
|
|
9
9
|
import { renderPosition } from "./position.js";
|
|
10
10
|
import { UNANSWERED } from "./query.js";
|
|
11
|
+
import { parenthesesRemoved } from "./unwrap.js";
|
|
11
12
|
/** The assignment operators that read their target before they write it. */
|
|
12
13
|
const COMPOUND = new Set([
|
|
13
14
|
SyntaxKind.PlusEqualsToken,
|
|
@@ -47,12 +48,9 @@ function useOf(node) {
|
|
|
47
48
|
}
|
|
48
49
|
return "read";
|
|
49
50
|
}
|
|
50
|
-
function unwrapped(node) {
|
|
51
|
-
return isParenthesizedExpression(node) ? unwrapped(node.expression) : node;
|
|
52
|
-
}
|
|
53
51
|
/** Whether an index is a literal the checker resolves to a member by its own text. */
|
|
54
52
|
function isLiteralIndex(node) {
|
|
55
|
-
const at =
|
|
53
|
+
const at = parenthesesRemoved(node);
|
|
56
54
|
return isStringLiteral(at) || isNumericLiteral(at) || isNoSubstitutionTemplateLiteral(at);
|
|
57
55
|
}
|
|
58
56
|
/**
|
|
@@ -195,7 +193,7 @@ export function elementAccessReferences(project, held, chains, root, testFiles)
|
|
|
195
193
|
const parameterOf = new Map();
|
|
196
194
|
const byCallable = new Map();
|
|
197
195
|
for (const candidate of candidates) {
|
|
198
|
-
const index =
|
|
196
|
+
const index = parenthesesRemoved(candidate.access.argumentExpression);
|
|
199
197
|
const fn = isIdentifier(index) ? enclosingFunction(candidate.access) : undefined;
|
|
200
198
|
const callable = fn === undefined ? undefined : callableOf(fn);
|
|
201
199
|
if (callable === undefined || !isIdentifier(index)) {
|
|
@@ -252,7 +250,7 @@ export function elementAccessReferences(project, held, chains, root, testFiles)
|
|
|
252
250
|
continue;
|
|
253
251
|
}
|
|
254
252
|
// An object that is a parameter too is read as the argument each call passes there.
|
|
255
|
-
const object =
|
|
253
|
+
const object = parenthesesRemoved(candidate.access.expression);
|
|
256
254
|
const objectAt = isIdentifier(object)
|
|
257
255
|
? deferred.callable.parameters.findIndex((parameter) => isIdentifier(parameter.name) && parameter.name.text === object.text)
|
|
258
256
|
: -1;
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* Every row carries a reason, because the list is read where the rows are shown
|
|
8
8
|
* one at a time: beside a finding, or in a report's declared gaps.
|
|
9
9
|
*/
|
|
10
|
+
import { bytewise } from "./text/compare.js";
|
|
10
11
|
/** What is declined for a tool whose own conventions are entered only through its configuration files. */
|
|
11
12
|
const EVERY_CONVENTION = "every file it loads by its own convention beyond its configuration files";
|
|
12
13
|
/** Why a tool whose own conventions are not read declines them. */
|
|
@@ -291,15 +292,8 @@ const PARTLY_ENTERED = [
|
|
|
291
292
|
reason: NOT_LITERAL,
|
|
292
293
|
},
|
|
293
294
|
];
|
|
294
|
-
/** Two strings ordered bytewise. */
|
|
295
|
-
function compare(a, b) {
|
|
296
|
-
if (a === b) {
|
|
297
|
-
return 0;
|
|
298
|
-
}
|
|
299
|
-
return a < b ? -1 : 1;
|
|
300
|
-
}
|
|
301
295
|
/** Every declined entry-point convention, ordered by tool and then by convention. */
|
|
302
296
|
export const DECLINED_CONVENTIONS = [
|
|
303
297
|
...UNREAD_TOOLS.map((tool) => ({ tool, convention: EVERY_CONVENTION, reason: UNREAD })),
|
|
304
298
|
...PARTLY_ENTERED,
|
|
305
|
-
].sort((a, b) =>
|
|
299
|
+
].sort((a, b) => bytewise(a.tool, b.tool) || bytewise(a.convention, b.convention));
|
package/dist/src/entry-points.js
CHANGED
|
@@ -10,17 +10,18 @@
|
|
|
10
10
|
* value that is not a literal is not evaluated and not guessed, so a file it would
|
|
11
11
|
* have named is entered by nothing here.
|
|
12
12
|
*/
|
|
13
|
-
import { isArrayLiteralExpression,
|
|
13
|
+
import { isArrayLiteralExpression, isCallExpression, isExportAssignment, isIdentifier, isMetaProperty, isNewExpression, isNoSubstitutionTemplateLiteral, isObjectLiteralExpression, isPropertyAccessExpression, isPropertyAssignment, isStringLiteral, SyntaxKind, } from "@typescript/native/ast";
|
|
14
14
|
import { SymbolFlags } from "@typescript/native/sync";
|
|
15
15
|
import { configurationFiles, filesNamedBy, moduleStrings, } from "./configuration-files.js";
|
|
16
16
|
import { buildScriptEntries } from "./build-scripts.js";
|
|
17
|
-
import { globExpression } from "./glob.js";
|
|
18
17
|
import { htmlEntries } from "./html-entries.js";
|
|
19
18
|
import { documentEntries } from "./mdx-entries.js";
|
|
20
19
|
import { dirnamePath, relativePath, resolvePath } from "./paths.js";
|
|
21
20
|
import { UNANSWERED } from "./query.js";
|
|
22
21
|
import { computedLoadDirectory, leadingLiteral } from "./unseen-loads.js";
|
|
23
22
|
import { workflowEntries } from "./workflow-steps.js";
|
|
23
|
+
import { unwrapped } from "./unwrap.js";
|
|
24
|
+
import { globExpression } from "./text/glob.js";
|
|
24
25
|
/** The extensions the test runner and the browser-test runner load a configuration from. */
|
|
25
26
|
const MODULE_EXTENSIONS = ["js", "mjs", "cjs", "ts", "mts", "cts"];
|
|
26
27
|
/** The tool file names the configuration form does not cover. */
|
|
@@ -69,14 +70,6 @@ function literalOf(node) {
|
|
|
69
70
|
}
|
|
70
71
|
return undefined;
|
|
71
72
|
}
|
|
72
|
-
/** The expression a wrapper that changes no value holds: parentheses and type assertions. */
|
|
73
|
-
function unwrapped(node) {
|
|
74
|
-
let at = node;
|
|
75
|
-
while (isParenthesizedExpression(at) || isAsExpression(at) || isSatisfiesExpression(at)) {
|
|
76
|
-
at = at.expression;
|
|
77
|
-
}
|
|
78
|
-
return at;
|
|
79
|
-
}
|
|
80
73
|
/**
|
|
81
74
|
* The object literals one configuration file's default export is written as: the
|
|
82
75
|
* literal itself, or each literal argument of the call it is, at any depth of calls.
|
package/dist/src/enum-group.js
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
* or `unknown` expression asserted to it, or bound to a variable or returned from a
|
|
7
7
|
* function it annotates, where a number counts too. An enum's own value converts nothing.
|
|
8
8
|
*/
|
|
9
|
-
import { isArrowFunction, isAsExpression, isElementAccessExpression, isEnumDeclaration, isFunctionDeclaration, isFunctionExpression, isGetAccessorDeclaration, isIdentifier, isMethodDeclaration, isNoSubstitutionTemplateLiteral,
|
|
9
|
+
import { isArrowFunction, isAsExpression, isElementAccessExpression, isEnumDeclaration, isFunctionDeclaration, isFunctionExpression, isGetAccessorDeclaration, isIdentifier, isMethodDeclaration, isNoSubstitutionTemplateLiteral, isParenthesizedTypeNode, isPropertyAccessExpression, isReturnStatement, isStringLiteral, isVariableDeclaration, SyntaxKind, } from "@typescript/native/ast";
|
|
10
|
+
import { parenthesesRemoved } from "./unwrap.js";
|
|
10
11
|
import { TypeFlags } from "@typescript/native/sync";
|
|
11
12
|
import { aliasChains } from "./alias-chain.js";
|
|
12
13
|
import { nodeKey } from "./inventory.js";
|
|
@@ -16,14 +17,6 @@ import { isAnswered, UNANSWERED } from "./query.js";
|
|
|
16
17
|
const NUMBER = TypeFlags.NumberLike;
|
|
17
18
|
const STRING = TypeFlags.StringLike;
|
|
18
19
|
const DECODED = TypeFlags.Any | TypeFlags.Unknown;
|
|
19
|
-
/** The expression one node is, through however many parentheses are written around it. */
|
|
20
|
-
function unparenthesized(node) {
|
|
21
|
-
let held = node;
|
|
22
|
-
while (isParenthesizedExpression(held)) {
|
|
23
|
-
held = held.expression;
|
|
24
|
-
}
|
|
25
|
-
return held;
|
|
26
|
-
}
|
|
27
20
|
/**
|
|
28
21
|
* The name node a type node names its declaration by: the identifier of a type
|
|
29
22
|
* reference, the right side of a qualified one, through parentheses. A type that is no
|
|
@@ -45,7 +38,7 @@ function typeName(type) {
|
|
|
45
38
|
}
|
|
46
39
|
/** The name node an expression names an object by: an identifier, or a property access's name. */
|
|
47
40
|
function objectName(expression) {
|
|
48
|
-
const held =
|
|
41
|
+
const held = parenthesesRemoved(expression);
|
|
49
42
|
if (isIdentifier(held)) {
|
|
50
43
|
return held;
|
|
51
44
|
}
|
|
@@ -6,10 +6,11 @@
|
|
|
6
6
|
* either stores. A store into an erased property of a type the analyzed program does not
|
|
7
7
|
* declare hands the value to the code that declares it.
|
|
8
8
|
*/
|
|
9
|
-
import { isArrayLiteralExpression, isBinaryExpression, isCallExpression, isElementAccessExpression, isIdentifier, isNoSubstitutionTemplateLiteral, isNumericLiteral, isObjectLiteralExpression,
|
|
9
|
+
import { isArrayLiteralExpression, isBinaryExpression, isCallExpression, isElementAccessExpression, isIdentifier, isNoSubstitutionTemplateLiteral, isNumericLiteral, isObjectLiteralExpression, isPropertyAccessExpression, isPropertyAssignment, isShorthandPropertyAssignment, isSpreadElement, isStringLiteral, isVariableDeclaration, SyntaxKind, } from "@typescript/native/ast";
|
|
10
10
|
import { SymbolFlags, TypeFlags } from "@typescript/native/sync";
|
|
11
11
|
import { must } from "./query.js";
|
|
12
12
|
import { checkedTypes } from "./value-reach.js";
|
|
13
|
+
import { parenthesesRemoved } from "./unwrap.js";
|
|
13
14
|
/** The types that keep nothing of the value they are given. */
|
|
14
15
|
const ERASED = TypeFlags.Any | TypeFlags.Unknown;
|
|
15
16
|
/** The array methods whose arguments become elements of the array they are called on. */
|
|
@@ -20,9 +21,6 @@ function literalKey(node) {
|
|
|
20
21
|
? node.text
|
|
21
22
|
: undefined;
|
|
22
23
|
}
|
|
23
|
-
function unwrapped(node) {
|
|
24
|
-
return isParenthesizedExpression(node) ? unwrapped(node.expression) : node;
|
|
25
|
-
}
|
|
26
24
|
/**
|
|
27
25
|
* Whether a variable declaration's type can differ from what is stored in it: it carries an
|
|
28
26
|
* annotation, or it has neither an annotation nor an initializer, so its type evolves.
|
|
@@ -76,8 +74,8 @@ function propertyAt(source, name) {
|
|
|
76
74
|
* here, and a default value is stored in its target too.
|
|
77
75
|
*/
|
|
78
76
|
function patternTargets(pattern, from, out) {
|
|
79
|
-
const target =
|
|
80
|
-
const source = from.path.length === 0 ?
|
|
77
|
+
const target = parenthesesRemoved(pattern);
|
|
78
|
+
const source = from.path.length === 0 ? parenthesesRemoved(from.value) : from.value;
|
|
81
79
|
const into = (element, step, literal) => {
|
|
82
80
|
patternTargets(element, literal === undefined
|
|
83
81
|
? { value: from.value, path: [...from.path, step] }
|