@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.
Files changed (201) hide show
  1. package/dist/bin/mapper-connection.js +2 -1
  2. package/dist/bin/node-host.js +3 -2
  3. package/dist/src/analysis.js +28 -46
  4. package/dist/src/automatic-types.js +10 -29
  5. package/dist/src/build-scripts.js +17 -29
  6. package/dist/src/component-layer.js +4 -2
  7. package/dist/src/components.js +2 -3
  8. package/dist/src/config.js +3 -2
  9. package/dist/src/configuration-files.js +27 -168
  10. package/dist/src/conformance-record.js +1 -1
  11. package/dist/src/contract/contract.generated.js +1084 -0
  12. package/dist/src/contract/report.generated.js +796 -0
  13. package/dist/src/conventions.js +20 -60
  14. package/dist/src/dependencies.js +25 -43
  15. package/dist/src/discover.js +13 -39
  16. package/dist/src/edges.js +7 -15
  17. package/dist/src/element-access.js +4 -6
  18. package/dist/src/entry-point-gaps.js +2 -8
  19. package/dist/src/entry-points.js +3 -10
  20. package/dist/src/enum-group.js +3 -10
  21. package/dist/src/erased-stores.js +4 -6
  22. package/dist/src/exempt-classes.js +3 -63
  23. package/dist/src/exempt.js +13 -40
  24. package/dist/src/file-facts.js +2 -25
  25. package/dist/src/findings/completion.js +11 -20
  26. package/dist/src/findings/dependencies-and-module-machinery.js +4 -5
  27. package/dist/src/findings/emitters.js +4 -4
  28. package/dist/src/findings/interfaces.js +4 -5
  29. package/dist/src/findings/intra-function.js +8 -7
  30. package/dist/src/findings/non-code-artifacts.js +5 -6
  31. package/dist/src/findings/reads-and-writes.js +11 -9
  32. package/dist/src/findings/self-check.js +10 -12
  33. package/dist/src/findings/unused-declarations.js +28 -27
  34. package/dist/src/findings/visibility-narrowing.js +9 -11
  35. package/dist/src/findings-pass.js +7 -14
  36. package/dist/src/fs/manifest.js +43 -0
  37. package/dist/src/fs/tree.js +88 -0
  38. package/dist/src/git-ignore.js +34 -25
  39. package/dist/src/html-entries.js +6 -33
  40. package/dist/src/in-operands.js +2 -1
  41. package/dist/src/index.js +1 -1
  42. package/dist/src/intra-function-parts.js +18 -26
  43. package/dist/src/inventory.js +2 -21
  44. package/dist/src/json-document.js +4 -0
  45. package/dist/src/keyof-comparisons.js +4 -6
  46. package/dist/src/kinds.js +4 -360
  47. package/dist/src/manifest.js +5 -43
  48. package/dist/src/mdx-entries.js +3 -26
  49. package/dist/src/partial.js +2 -1
  50. package/dist/src/paths.js +26 -15
  51. package/dist/src/position.js +2 -1
  52. package/dist/src/print.js +3 -2
  53. package/dist/src/product.js +13 -0
  54. package/dist/src/references.js +14 -27
  55. package/dist/src/report-schema.js +272 -0
  56. package/dist/src/report.js +39 -42
  57. package/dist/src/reporters/sarif.js +4 -2
  58. package/dist/src/reporters/template.js +4 -19
  59. package/dist/src/resolve.js +12 -26
  60. package/dist/src/roots.js +7 -17
  61. package/dist/src/run.js +10 -8
  62. package/dist/src/schema.js +4 -3
  63. package/dist/src/scope.js +4 -5
  64. package/dist/src/serialization-contract.js +4 -8
  65. package/dist/src/session.js +2 -1
  66. package/dist/src/setup-failure.js +2 -6
  67. package/dist/src/suppress-file.js +12 -13
  68. package/dist/src/suppress-inline.js +3 -2
  69. package/dist/src/suppress.js +29 -48
  70. package/dist/src/symbol-keys.js +3 -5
  71. package/dist/src/template-field.js +5 -15
  72. package/dist/src/test-globals.js +6 -28
  73. package/dist/src/test-joins.js +6 -6
  74. package/dist/src/text/compare.js +26 -0
  75. package/dist/src/text/glob.js +194 -0
  76. package/dist/src/text/shell.js +159 -0
  77. package/dist/src/{yaml-document.js → text/yaml.js} +38 -0
  78. package/dist/src/type-errors.js +14 -38
  79. package/dist/src/unseen-loads.js +2 -9
  80. package/dist/src/unwrap.js +23 -0
  81. package/dist/src/verbs/analyze.js +22 -15
  82. package/dist/src/verbs/describe.js +7 -7
  83. package/dist/src/verbs/explain.js +7 -4
  84. package/dist/src/verbs/print-config.js +2 -1
  85. package/dist/src/verbs/print-projects.js +4 -2
  86. package/dist/src/verbs/print-retained.js +4 -2
  87. package/dist/src/verbs/print-roots.js +4 -2
  88. package/dist/src/verbs/verb.js +1 -5
  89. package/dist/src/verbs/version.js +4 -3
  90. package/dist/src/workflow-steps.js +9 -46
  91. package/dist/src/workspace-manifests.js +2 -2
  92. package/dist/src/workspace-programs.js +5 -3
  93. package/dist/src/workspace-resolution.js +13 -17
  94. package/dist/src/workspace.js +28 -116
  95. package/jsr.json +1 -1
  96. package/package.json +2 -1
  97. package/src/analysis.ts +29 -54
  98. package/src/automatic-types.ts +11 -29
  99. package/src/build-scripts.ts +17 -38
  100. package/src/component-layer.ts +4 -2
  101. package/src/components.ts +2 -4
  102. package/src/config.ts +11 -15
  103. package/src/configuration-files.ts +27 -170
  104. package/src/conformance-record.ts +1 -1
  105. package/src/contract/contract.generated.ts +1148 -0
  106. package/src/contract/report.generated.ts +1157 -0
  107. package/src/conventions.ts +26 -74
  108. package/src/dependencies.ts +32 -50
  109. package/src/discover.ts +14 -39
  110. package/src/edges.ts +7 -21
  111. package/src/element-access.ts +4 -7
  112. package/src/entry-point-gaps.ts +3 -9
  113. package/src/entry-points.ts +2 -13
  114. package/src/enum-group.ts +2 -11
  115. package/src/erased-stores.ts +3 -7
  116. package/src/exempt-classes.ts +5 -74
  117. package/src/exempt.ts +17 -47
  118. package/src/file-facts.ts +6 -24
  119. package/src/finding.ts +9 -9
  120. package/src/findings/completion.ts +22 -23
  121. package/src/findings/dependencies-and-module-machinery.ts +4 -7
  122. package/src/findings/emitter.ts +6 -7
  123. package/src/findings/emitters.ts +6 -6
  124. package/src/findings/interfaces.ts +4 -6
  125. package/src/findings/intra-function.ts +8 -8
  126. package/src/findings/non-code-artifacts.ts +5 -7
  127. package/src/findings/reads-and-writes.ts +15 -12
  128. package/src/findings/self-check.ts +11 -17
  129. package/src/findings/unused-declarations.ts +28 -27
  130. package/src/findings/visibility-narrowing.ts +9 -12
  131. package/src/findings-pass.ts +7 -16
  132. package/src/fs/manifest.ts +52 -0
  133. package/src/fs/tree.ts +110 -0
  134. package/src/git-ignore.ts +38 -25
  135. package/src/html-entries.ts +6 -33
  136. package/src/in-operands.ts +2 -1
  137. package/src/index.ts +1 -1
  138. package/src/intra-function-parts.ts +18 -28
  139. package/src/inventory.ts +2 -20
  140. package/src/json-document.ts +5 -0
  141. package/src/keyof-comparisons.ts +3 -7
  142. package/src/kinds.ts +6 -406
  143. package/src/manifest.ts +5 -46
  144. package/src/mdx-entries.ts +3 -26
  145. package/src/partial.ts +2 -1
  146. package/src/paths.ts +27 -15
  147. package/src/position.ts +2 -1
  148. package/src/print.ts +3 -2
  149. package/src/product.ts +18 -0
  150. package/src/references.ts +14 -29
  151. package/src/report-schema.ts +364 -0
  152. package/src/report.ts +66 -229
  153. package/src/reporters/annotations.ts +2 -2
  154. package/src/reporters/json.ts +1 -1
  155. package/src/reporters/reporter.ts +2 -2
  156. package/src/reporters/reporters.ts +1 -1
  157. package/src/reporters/sarif.ts +17 -12
  158. package/src/reporters/template.ts +4 -20
  159. package/src/reporters/text.ts +3 -3
  160. package/src/resolve.ts +31 -38
  161. package/src/roots.ts +7 -20
  162. package/src/run.ts +10 -14
  163. package/src/schema.ts +4 -3
  164. package/src/scope.ts +4 -10
  165. package/src/serialization-contract.ts +4 -9
  166. package/src/session.ts +2 -1
  167. package/src/setup-failure.ts +5 -7
  168. package/src/suppress-file.ts +11 -15
  169. package/src/suppress-inline.ts +2 -2
  170. package/src/suppress.ts +39 -55
  171. package/src/symbol-keys.ts +2 -5
  172. package/src/template-field.ts +5 -18
  173. package/src/test-globals.ts +9 -27
  174. package/src/test-joins.ts +6 -8
  175. package/src/text/compare.ts +27 -0
  176. package/src/text/glob.ts +210 -0
  177. package/src/text/shell.ts +161 -0
  178. package/src/{yaml-document.ts → text/yaml.ts} +46 -0
  179. package/src/type-errors.ts +25 -36
  180. package/src/unseen-loads.ts +1 -12
  181. package/src/unwrap.ts +34 -0
  182. package/src/verbs/analyze.ts +38 -25
  183. package/src/verbs/describe.ts +13 -7
  184. package/src/verbs/explain.ts +7 -4
  185. package/src/verbs/print-config.ts +2 -1
  186. package/src/verbs/print-projects.ts +4 -2
  187. package/src/verbs/print-retained.ts +4 -2
  188. package/src/verbs/print-roots.ts +4 -2
  189. package/src/verbs/verb.ts +0 -6
  190. package/src/verbs/version.ts +4 -3
  191. package/src/workflow-steps.ts +9 -44
  192. package/src/workspace-manifests.ts +2 -2
  193. package/src/workspace-programs.ts +5 -3
  194. package/src/workspace-resolution.ts +21 -17
  195. package/src/workspace.ts +35 -121
  196. package/dist/src/glob.js +0 -65
  197. package/dist/src/pnpm-workspace.js +0 -120
  198. package/dist/src/version.js +0 -7
  199. package/src/glob.ts +0 -67
  200. package/src/pnpm-workspace.ts +0 -135
  201. 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
- /** The codes of the parts this module reads. */
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 = unwrapped(call.expression);
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 = unwrapped(expression);
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 = unwrapped(type.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 = unwrapped(expression);
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(unwrapped(node.expression))) {
451
- specifiers.add(position(unwrapped(node.expression)));
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: DEAD_STORE,
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: DEAD_STORE,
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: UNREACHABLE_STATEMENT,
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: UNREACHABLE_CASE,
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: UNUSED_PARAMETER,
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
- unwrapped(parent.left) === use);
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: DEAD_STORE,
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 = unwrapped(statement.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 = unwrapped(expression.left);
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: UNUSED_RESULT,
1075
+ code: CODE.unusedResult,
1084
1076
  declaration: id,
1085
1077
  kind: "result",
1086
1078
  name: "result",
@@ -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
- const MANIFEST = "package.json";
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
- let text;
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, isParenthesizedExpression, isPropertyAccessExpression, isSwitchStatement, isTypeOperatorNode, SyntaxKind, } from "@typescript/native/ast";
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 = unwrapped(node);
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(unwrapped(one.other))
97
+ return name === undefined || isElementAccessExpression(parenthesesRemoved(one.other))
100
98
  ? []
101
99
  : [{ ...one, name }];
102
100
  });