@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
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* call sites that use or discard it, each statement control flow cannot reach, each
|
|
5
5
|
* write to a local that no read reaches, and each case an earlier case covers.
|
|
6
6
|
*/
|
|
7
|
+
import { CODE } from "./contract/contract.generated.js";
|
|
7
8
|
import { isArrowFunction, isAwaitExpression, isBigIntLiteral, isBinaryExpression, isBlock, isBreakStatement, isBindingElement, isCallExpression, isCaseClause, isCatchClause, isClassDeclaration, isClassExpression, isConstructorDeclaration, isContinueStatement, isDecorator, isDefaultClause, isEmptyStatement, isExportAssignment, isExportSpecifier, isExpressionStatement, isFunctionDeclaration, isFunctionExpression, isForInStatement, isForOfStatement, isFunctionLikeDeclaration, isHeritageClause, isIdentifier, isIfStatement, isImportClause, isImportSpecifier, isInterfaceDeclaration, isMethodDeclaration, isModuleDeclaration, isNamespaceImport, isNewExpression, isNoSubstitutionTemplateLiteral, isNumericLiteral, isObjectBindingPattern, isObjectLiteralExpression, isParenthesizedExpression, isPrefixUnaryExpression, isPropertyAssignment, isPropertyAccessExpression, isQualifiedName, isReturnStatement, isShorthandPropertyAssignment, isSourceFile, isStringLiteral, isSwitchStatement, isThrowStatement, isTypeAliasDeclaration, isTypeReferenceNode, isVariableDeclarationList, isVariableStatement, isVoidExpression, NodeFlags, SyntaxKind, } from "@typescript/native/ast";
|
|
8
9
|
import { SignatureKind } from "@typescript/native/sync";
|
|
9
10
|
import { exportsLocally, implicitReads, importBindings, } from "./import-bindings.js";
|
|
@@ -13,12 +14,7 @@ import { importRef } from "./ref.js";
|
|
|
13
14
|
import { isAnswered, UNANSWERED } from "./query.js";
|
|
14
15
|
import { signatureOf } from "./signatures.js";
|
|
15
16
|
import { spellsNoBinding } from "./spelled-names.js";
|
|
16
|
-
|
|
17
|
-
export const UNUSED_PARAMETER = "DS1801";
|
|
18
|
-
export const UNUSED_RESULT = "DS1803";
|
|
19
|
-
const UNREACHABLE_STATEMENT = "DS1805";
|
|
20
|
-
const DEAD_STORE = "DS1807";
|
|
21
|
-
const UNREACHABLE_CASE = "DS1809";
|
|
17
|
+
import { parenthesesRemoved } from "./unwrap.js";
|
|
22
18
|
/** The result types that carry no value, as the checker spells them. */
|
|
23
19
|
const NO_VALUE = new Set([
|
|
24
20
|
"void",
|
|
@@ -34,17 +30,13 @@ function spanOf(file, root, node) {
|
|
|
34
30
|
const endLine = file.getLineAndCharacterOfPosition(node.end).line + 1;
|
|
35
31
|
return { ...start, endLine };
|
|
36
32
|
}
|
|
37
|
-
/** The parenthesized expression's content, through every pair of parentheses. */
|
|
38
|
-
function unwrapped(node) {
|
|
39
|
-
return isParenthesizedExpression(node) ? unwrapped(node.expression) : node;
|
|
40
|
-
}
|
|
41
33
|
/** The node the parentheses around one expression sit in. */
|
|
42
34
|
function outerParent(node) {
|
|
43
35
|
return isParenthesizedExpression(node.parent) ? outerParent(node.parent) : node.parent;
|
|
44
36
|
}
|
|
45
37
|
/** The name a call is made through: the identifier, or the member a property access names. */
|
|
46
38
|
function calleeName(call) {
|
|
47
|
-
const callee =
|
|
39
|
+
const callee = parenthesesRemoved(call.expression);
|
|
48
40
|
if (isIdentifier(callee)) {
|
|
49
41
|
return callee;
|
|
50
42
|
}
|
|
@@ -99,7 +91,7 @@ function unreachableExempt(statement) {
|
|
|
99
91
|
}
|
|
100
92
|
/** The value a case expression is a literal of, as a key two equal literals share, or none. */
|
|
101
93
|
function caseKey(expression) {
|
|
102
|
-
const node =
|
|
94
|
+
const node = parenthesesRemoved(expression);
|
|
103
95
|
if (isStringLiteral(node) || isNoSubstitutionTemplateLiteral(node)) {
|
|
104
96
|
return `s:${node.text}`;
|
|
105
97
|
}
|
|
@@ -210,7 +202,7 @@ function extendedNames(files) {
|
|
|
210
202
|
named = isQualifiedName(type.typeName) ? type.typeName.right : type.typeName;
|
|
211
203
|
}
|
|
212
204
|
else {
|
|
213
|
-
const expression =
|
|
205
|
+
const expression = parenthesesRemoved(type.expression);
|
|
214
206
|
named = isPropertyAccessExpression(expression) ? expression.name : expression;
|
|
215
207
|
}
|
|
216
208
|
if (isIdentifier(named)) {
|
|
@@ -254,7 +246,7 @@ function decoratorFixes(constructor) {
|
|
|
254
246
|
}
|
|
255
247
|
/** The name an expression spells a class by: an identifier, or the member a property access names. */
|
|
256
248
|
function spelledName(expression) {
|
|
257
|
-
const node =
|
|
249
|
+
const node = parenthesesRemoved(expression);
|
|
258
250
|
if (isIdentifier(node)) {
|
|
259
251
|
return node;
|
|
260
252
|
}
|
|
@@ -447,8 +439,8 @@ export function projectParts(project, held, references, targetRoot) {
|
|
|
447
439
|
if ((isImportClause(node) || isNamespaceImport(node)) && node.name !== undefined) {
|
|
448
440
|
specifiers.add(position(node.name));
|
|
449
441
|
}
|
|
450
|
-
if (isExportAssignment(node) && isIdentifier(
|
|
451
|
-
specifiers.add(position(
|
|
442
|
+
if (isExportAssignment(node) && isIdentifier(parenthesesRemoved(node.expression))) {
|
|
443
|
+
specifiers.add(position(parenthesesRemoved(node.expression)));
|
|
452
444
|
}
|
|
453
445
|
if (isSwitchStatement(node)) {
|
|
454
446
|
const holder = holderOf(node);
|
|
@@ -572,7 +564,7 @@ export function projectParts(project, held, references, targetRoot) {
|
|
|
572
564
|
}
|
|
573
565
|
walk.catches.forEach(({ name, holder }, at) => {
|
|
574
566
|
parts.push({
|
|
575
|
-
code:
|
|
567
|
+
code: CODE.deadStore,
|
|
576
568
|
declaration: holder,
|
|
577
569
|
kind: "store",
|
|
578
570
|
name: name.text,
|
|
@@ -584,7 +576,7 @@ export function projectParts(project, held, references, targetRoot) {
|
|
|
584
576
|
for (const { names, uses, holder } of loopVariables) {
|
|
585
577
|
for (const name of names) {
|
|
586
578
|
parts.push({
|
|
587
|
-
code:
|
|
579
|
+
code: CODE.deadStore,
|
|
588
580
|
declaration: holder,
|
|
589
581
|
kind: "store",
|
|
590
582
|
name: name.text,
|
|
@@ -602,7 +594,7 @@ export function projectParts(project, held, references, targetRoot) {
|
|
|
602
594
|
});
|
|
603
595
|
for (const { statement, holder } of walk.unreachable) {
|
|
604
596
|
parts.push({
|
|
605
|
-
code:
|
|
597
|
+
code: CODE.unreachableStatement,
|
|
606
598
|
declaration: holder,
|
|
607
599
|
kind: "statement",
|
|
608
600
|
name: "statement",
|
|
@@ -613,7 +605,7 @@ export function projectParts(project, held, references, targetRoot) {
|
|
|
613
605
|
}
|
|
614
606
|
for (const { clause, text, holder } of walk.cases) {
|
|
615
607
|
parts.push({
|
|
616
|
-
code:
|
|
608
|
+
code: CODE.unreachableCase,
|
|
617
609
|
declaration: holder,
|
|
618
610
|
kind: "case",
|
|
619
611
|
name: text,
|
|
@@ -826,7 +818,7 @@ function parameterParts(file, root, declaration, signature, reader, ids, place)
|
|
|
826
818
|
return;
|
|
827
819
|
}
|
|
828
820
|
const part = {
|
|
829
|
-
code:
|
|
821
|
+
code: CODE.unusedParameter,
|
|
830
822
|
declaration,
|
|
831
823
|
kind: "parameter",
|
|
832
824
|
name: name.text,
|
|
@@ -951,7 +943,7 @@ function isPlainWrite(use) {
|
|
|
951
943
|
const parent = outerParent(use);
|
|
952
944
|
return (isBinaryExpression(parent) &&
|
|
953
945
|
parent.operatorToken.kind === SyntaxKind.EqualsToken &&
|
|
954
|
-
|
|
946
|
+
parenthesesRemoved(parent.left) === use);
|
|
955
947
|
}
|
|
956
948
|
/**
|
|
957
949
|
* The writes to the locals of one block that no read reaches. A write is a declaration's
|
|
@@ -964,7 +956,7 @@ function isPlainWrite(use) {
|
|
|
964
956
|
function deadStores(file, root, block, holder, locals, ids) {
|
|
965
957
|
const found = [];
|
|
966
958
|
const deadAt = (local, target) => ({
|
|
967
|
-
code:
|
|
959
|
+
code: CODE.deadStore,
|
|
968
960
|
declaration: holder,
|
|
969
961
|
kind: "store",
|
|
970
962
|
name: local.name.text,
|
|
@@ -997,12 +989,12 @@ function deadStores(file, root, block, holder, locals, ids) {
|
|
|
997
989
|
if (!isExpressionStatement(statement)) {
|
|
998
990
|
return undefined;
|
|
999
991
|
}
|
|
1000
|
-
const expression =
|
|
992
|
+
const expression = parenthesesRemoved(statement.expression);
|
|
1001
993
|
if (!isBinaryExpression(expression) ||
|
|
1002
994
|
expression.operatorToken.kind !== SyntaxKind.EqualsToken) {
|
|
1003
995
|
return undefined;
|
|
1004
996
|
}
|
|
1005
|
-
const target =
|
|
997
|
+
const target = parenthesesRemoved(expression.left);
|
|
1006
998
|
return isIdentifier(target) && uses.includes(target)
|
|
1007
999
|
? { target, value: expression.right }
|
|
1008
1000
|
: undefined;
|
|
@@ -1080,7 +1072,7 @@ function resultParts(project, root, sites, references, calls) {
|
|
|
1080
1072
|
const valued = project.queries.nonNullable(result);
|
|
1081
1073
|
const members = isAnswered(valued) ? project.queries.propertiesOf(valued) : UNANSWERED;
|
|
1082
1074
|
found.push({
|
|
1083
|
-
code:
|
|
1075
|
+
code: CODE.unusedResult,
|
|
1084
1076
|
declaration: id,
|
|
1085
1077
|
kind: "result",
|
|
1086
1078
|
name: "result",
|
package/dist/src/inventory.js
CHANGED
|
@@ -3,7 +3,7 @@ import { dirnamePath, joinPath, relativePath } from "./paths.js";
|
|
|
3
3
|
import { byPosition, positionKey, renderPosition, writtenLength, } from "./position.js";
|
|
4
4
|
import { computedComponent, nameComponent, renderRef } from "./ref.js";
|
|
5
5
|
import { isAnswered, UNANSWERED } from "./query.js";
|
|
6
|
-
|
|
6
|
+
import { manifestAt } from "./fs/manifest.js";
|
|
7
7
|
/**
|
|
8
8
|
* Resolves each file's package scope: the name of the nearest manifest at or above
|
|
9
9
|
* its directory up to the target root, and the file's path below that manifest.
|
|
@@ -17,26 +17,7 @@ const MANIFEST = "package.json";
|
|
|
17
17
|
export function packageScope(host, root) {
|
|
18
18
|
const named = new Map();
|
|
19
19
|
const manifestName = (dir) => {
|
|
20
|
-
|
|
21
|
-
try {
|
|
22
|
-
text = host.readFile(joinPath(root, dir, MANIFEST));
|
|
23
|
-
}
|
|
24
|
-
catch {
|
|
25
|
-
return undefined;
|
|
26
|
-
}
|
|
27
|
-
let value;
|
|
28
|
-
try {
|
|
29
|
-
value = JSON.parse(text);
|
|
30
|
-
}
|
|
31
|
-
catch {
|
|
32
|
-
// A manifest this program cannot read names no package, which is the same
|
|
33
|
-
// answer as an absent one: the file is then scoped by the target root.
|
|
34
|
-
return undefined;
|
|
35
|
-
}
|
|
36
|
-
if (typeof value !== "object" || value === null) {
|
|
37
|
-
return undefined;
|
|
38
|
-
}
|
|
39
|
-
const name = value["name"];
|
|
20
|
+
const name = manifestAt(host, joinPath(root, dir))?.["name"];
|
|
40
21
|
return typeof name === "string" && name !== "" ? name : undefined;
|
|
41
22
|
};
|
|
42
23
|
const nearest = (dir) => {
|
|
@@ -111,3 +111,7 @@ export function positionAt(text, file, offset) {
|
|
|
111
111
|
const lineStart = before.lastIndexOf("\n") + 1;
|
|
112
112
|
return { path: file, line: before.split("\n").length, column: offset - lineStart + 1 };
|
|
113
113
|
}
|
|
114
|
+
/** Whether a decoded JSON value is an object: not `null` and not an array. */
|
|
115
|
+
export function isRecord(value) {
|
|
116
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
117
|
+
}
|
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
* that holds `keyof X`, the literal the other side has names the member of `X` under that
|
|
5
5
|
* key, because deleting the member makes the comparison a type error.
|
|
6
6
|
*/
|
|
7
|
-
import { isBinaryExpression, isCaseClause, isElementAccessExpression, isIdentifier,
|
|
7
|
+
import { isBinaryExpression, isCaseClause, isElementAccessExpression, isIdentifier, isPropertyAccessExpression, isSwitchStatement, isTypeOperatorNode, SyntaxKind, } from "@typescript/native/ast";
|
|
8
8
|
import { SymbolFlags } from "@typescript/native/sync";
|
|
9
9
|
import { nodeKey } from "./inventory.js";
|
|
10
10
|
import { renderPosition } from "./position.js";
|
|
11
11
|
import { UNANSWERED } from "./query.js";
|
|
12
|
+
import { parenthesesRemoved } from "./unwrap.js";
|
|
12
13
|
/** The operators that compare their operands for equality. */
|
|
13
14
|
const EQUALITIES = new Set([
|
|
14
15
|
SyntaxKind.EqualsEqualsEqualsToken,
|
|
@@ -16,12 +17,9 @@ const EQUALITIES = new Set([
|
|
|
16
17
|
SyntaxKind.EqualsEqualsToken,
|
|
17
18
|
SyntaxKind.ExclamationEqualsToken,
|
|
18
19
|
]);
|
|
19
|
-
function unwrapped(node) {
|
|
20
|
-
return isParenthesizedExpression(node) ? unwrapped(node.expression) : node;
|
|
21
|
-
}
|
|
22
20
|
/** The name node an operand's symbol is read at: an identifier, or a property access's name. */
|
|
23
21
|
function nameOf(node) {
|
|
24
|
-
const at =
|
|
22
|
+
const at = parenthesesRemoved(node);
|
|
25
23
|
if (isIdentifier(at)) {
|
|
26
24
|
return at;
|
|
27
25
|
}
|
|
@@ -96,7 +94,7 @@ export function keyofComparisonReferences(project, held, chains, root, testFiles
|
|
|
96
94
|
}
|
|
97
95
|
const named = comparisons.flatMap((one) => {
|
|
98
96
|
const name = nameOf(one.keyed);
|
|
99
|
-
return name === undefined || isElementAccessExpression(
|
|
97
|
+
return name === undefined || isElementAccessExpression(parenthesesRemoved(one.other))
|
|
100
98
|
? []
|
|
101
99
|
: [{ ...one, name }];
|
|
102
100
|
});
|