@cplieger/deadset-ts 7.2.0-dev.4 → 8.0.0-dev.10

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 (288) hide show
  1. package/README.md +1 -1
  2. package/dist/bin/mapper-connection.js +2 -1
  3. package/dist/bin/node-host.js +24 -5
  4. package/dist/src/analysis.js +245 -309
  5. package/dist/src/augmentations.js +124 -18
  6. package/dist/src/automatic-types.js +170 -0
  7. package/dist/src/build-scripts.js +425 -0
  8. package/dist/src/component-layer.js +4 -2
  9. package/dist/src/components.js +9 -9
  10. package/dist/src/config.js +6 -81
  11. package/dist/src/configuration-files.js +78 -188
  12. package/dist/src/configured-declarations.js +15 -20
  13. package/dist/src/conformance-record.js +2 -2
  14. package/dist/src/consumers.js +3 -30
  15. package/dist/src/contextual-uses.js +56 -9
  16. package/dist/src/contract/config.generated.js +558 -0
  17. package/dist/src/contract/contract.generated.js +1244 -0
  18. package/dist/src/contract/report.generated.js +862 -0
  19. package/dist/src/convention-rows.js +146 -1
  20. package/dist/src/conventions.js +136 -70
  21. package/dist/src/decorator.js +21 -18
  22. package/dist/src/dependencies.js +280 -62
  23. package/dist/src/edges.js +38 -122
  24. package/dist/src/element-access.js +4 -6
  25. package/dist/src/entry-point-gaps.js +9 -18
  26. package/dist/src/entry-points.js +106 -21
  27. package/dist/src/enum-group.js +3 -10
  28. package/dist/src/erased-stores.js +4 -6
  29. package/dist/src/exempt-classes.js +1 -63
  30. package/dist/src/exempt.js +21 -40
  31. package/dist/src/failure.js +36 -0
  32. package/dist/src/file-facts.js +2 -25
  33. package/dist/src/findings/completion.js +225 -63
  34. package/dist/src/findings/dependencies-and-module-machinery.js +72 -27
  35. package/dist/src/findings/emitters.js +6 -6
  36. package/dist/src/findings/interfaces.js +4 -5
  37. package/dist/src/findings/intra-function.js +53 -19
  38. package/dist/src/findings/non-code-artifacts.js +71 -39
  39. package/dist/src/findings/reads-and-writes.js +16 -13
  40. package/dist/src/findings/self-check.js +10 -12
  41. package/dist/src/findings/unused-declarations.js +57 -28
  42. package/dist/src/findings/visibility-narrowing.js +40 -18
  43. package/dist/src/findings-pass.js +8 -15
  44. package/dist/src/framework-lifecycle.js +7 -7
  45. package/dist/src/fs/document.js +52 -0
  46. package/dist/src/fs/manifest.js +72 -0
  47. package/dist/src/fs/tree.js +88 -0
  48. package/dist/src/generated-file.js +18 -4
  49. package/dist/src/git-ignore.js +99 -0
  50. package/dist/src/graph.js +9 -4
  51. package/dist/src/html-entries.js +6 -33
  52. package/dist/src/import-bindings.js +97 -0
  53. package/dist/src/in-operands.js +2 -1
  54. package/dist/src/index.js +1 -1
  55. package/dist/src/indexed-access.js +130 -28
  56. package/dist/src/injection-container.js +1 -1
  57. package/dist/src/interface-satisfaction.js +30 -12
  58. package/dist/src/intra-function-parts.js +341 -69
  59. package/dist/src/inventory.js +54 -29
  60. package/dist/src/javascript-file.js +33 -0
  61. package/dist/src/json-document.js +198 -67
  62. package/dist/src/keyof-comparisons.js +4 -6
  63. package/dist/src/kinds.js +3 -366
  64. package/dist/src/load/classify.js +270 -0
  65. package/dist/src/load/diagnostics.js +80 -0
  66. package/dist/src/load/discover.js +277 -0
  67. package/dist/src/{emit-map.js → load/emit-map.js} +1 -1
  68. package/dist/src/load/expected-module.js +136 -0
  69. package/dist/src/load/load.js +27 -0
  70. package/dist/src/load/module-lookup.js +37 -0
  71. package/dist/src/load/plan.js +313 -0
  72. package/dist/src/load/specifiers.js +115 -0
  73. package/dist/src/load/synthesize.js +140 -0
  74. package/dist/src/load/test-globals.js +207 -0
  75. package/dist/src/load/test-joins.js +82 -0
  76. package/dist/src/{workspace-manifests.js → load/workspace-manifests.js} +4 -4
  77. package/dist/src/{workspace-programs.js → load/workspace-programs.js} +88 -61
  78. package/dist/src/{workspace-resolution.js → load/workspace-resolution.js} +60 -59
  79. package/dist/src/{workspace-run.js → load/workspace-run.js} +7 -7
  80. package/dist/src/{workspace.js → load/workspace.js} +62 -124
  81. package/dist/src/manifest.js +49 -54
  82. package/dist/src/matrix.js +94 -13
  83. package/dist/src/mdx-entries.js +174 -0
  84. package/dist/src/module-declarations.js +9 -13
  85. package/dist/src/outside-tests.js +1 -1
  86. package/dist/src/overrides.js +41 -10
  87. package/dist/src/partial.js +2 -1
  88. package/dist/src/paths.js +26 -15
  89. package/dist/src/position.js +2 -1
  90. package/dist/src/print.js +11 -78
  91. package/dist/src/product.js +13 -0
  92. package/dist/src/query.js +1 -0
  93. package/dist/src/ref.js +11 -0
  94. package/dist/src/references.js +52 -31
  95. package/dist/src/report-schema.js +51 -0
  96. package/dist/src/report.js +59 -41
  97. package/dist/src/reporters/annotations.js +15 -8
  98. package/dist/src/reporters/sarif.js +16 -10
  99. package/dist/src/reporters/template.js +4 -19
  100. package/dist/src/resolve.js +245 -727
  101. package/dist/src/roots.js +374 -116
  102. package/dist/src/run.js +66 -77
  103. package/dist/src/schema.js +320 -342
  104. package/dist/src/scope.js +38 -115
  105. package/dist/src/serialization-contract.js +649 -29
  106. package/dist/src/session.js +41 -29
  107. package/dist/src/source-files.js +40 -15
  108. package/dist/src/suppress-file.js +34 -29
  109. package/dist/src/suppress-inline.js +21 -4
  110. package/dist/src/suppress.js +40 -56
  111. package/dist/src/sweep.js +32 -17
  112. package/dist/src/symbol-keys.js +105 -6
  113. package/dist/src/template-field.js +9 -19
  114. package/dist/src/test-support.js +119 -18
  115. package/dist/src/text/compare.js +26 -0
  116. package/dist/src/text/glob.js +194 -0
  117. package/dist/src/text/named-files.js +54 -0
  118. package/dist/src/text/shell.js +159 -0
  119. package/dist/src/text/yaml.js +393 -0
  120. package/dist/src/type-errors.js +27 -221
  121. package/dist/src/type-parameter-reads.js +172 -0
  122. package/dist/src/unseen-loads.js +100 -0
  123. package/dist/src/unwrap.js +23 -0
  124. package/dist/src/usage.js +10 -0
  125. package/dist/src/verbs/analyze.js +181 -125
  126. package/dist/src/verbs/describe.js +9 -16
  127. package/dist/src/verbs/explain.js +14 -9
  128. package/dist/src/verbs/print-config.js +2 -1
  129. package/dist/src/verbs/print-projects.js +6 -4
  130. package/dist/src/verbs/print-retained.js +4 -2
  131. package/dist/src/verbs/print-roots.js +4 -2
  132. package/dist/src/verbs/verb.js +1 -5
  133. package/dist/src/verbs/version.js +14 -3
  134. package/dist/src/workflow-steps.js +128 -33
  135. package/jsr.json +1 -1
  136. package/package.json +5 -4
  137. package/src/analysis.ts +333 -457
  138. package/src/augmentations.ts +152 -23
  139. package/src/automatic-types.ts +228 -0
  140. package/src/build-scripts.ts +543 -0
  141. package/src/component-layer.ts +4 -2
  142. package/src/components.ts +9 -10
  143. package/src/config.ts +31 -299
  144. package/src/configuration-files.ts +100 -191
  145. package/src/configured-declarations.ts +18 -23
  146. package/src/conformance-record.ts +2 -2
  147. package/src/consumers.ts +6 -57
  148. package/src/contextual-uses.ts +64 -12
  149. package/src/contract/config.generated.ts +818 -0
  150. package/src/contract/contract.generated.ts +1308 -0
  151. package/src/contract/report.generated.ts +1237 -0
  152. package/src/convention-rows.ts +186 -1
  153. package/src/conventions.ts +166 -90
  154. package/src/decorator.ts +28 -18
  155. package/src/dependencies.ts +356 -78
  156. package/src/edges.ts +41 -140
  157. package/src/element-access.ts +4 -7
  158. package/src/entry-point-gaps.ts +11 -20
  159. package/src/entry-points.ts +124 -28
  160. package/src/enum-group.ts +2 -11
  161. package/src/erased-stores.ts +3 -7
  162. package/src/exempt-classes.ts +1 -75
  163. package/src/exempt.ts +36 -50
  164. package/src/failure.ts +63 -0
  165. package/src/file-facts.ts +9 -24
  166. package/src/finding.ts +24 -9
  167. package/src/findings/boundary.ts +2 -0
  168. package/src/findings/completion.ts +297 -77
  169. package/src/findings/dependencies-and-module-machinery.ts +90 -31
  170. package/src/findings/emitter.ts +8 -9
  171. package/src/findings/emitters.ts +8 -8
  172. package/src/findings/interfaces.ts +4 -6
  173. package/src/findings/intra-function.ts +64 -20
  174. package/src/findings/non-code-artifacts.ts +88 -50
  175. package/src/findings/reads-and-writes.ts +20 -16
  176. package/src/findings/self-check.ts +11 -17
  177. package/src/findings/unused-declarations.ts +65 -28
  178. package/src/findings/visibility-narrowing.ts +51 -19
  179. package/src/findings-pass.ts +10 -19
  180. package/src/framework-lifecycle.ts +7 -7
  181. package/src/fs/document.ts +70 -0
  182. package/src/fs/manifest.ts +92 -0
  183. package/src/fs/tree.ts +110 -0
  184. package/src/generated-file.ts +23 -4
  185. package/src/git-ignore.ts +122 -0
  186. package/src/graph.ts +11 -3
  187. package/src/host.ts +17 -14
  188. package/src/html-entries.ts +6 -33
  189. package/src/import-bindings.ts +128 -0
  190. package/src/in-operands.ts +2 -1
  191. package/src/index.ts +1 -1
  192. package/src/indexed-access.ts +152 -30
  193. package/src/injection-container.ts +1 -1
  194. package/src/interface-satisfaction.ts +33 -13
  195. package/src/intra-function-parts.ts +449 -85
  196. package/src/inventory.ts +73 -27
  197. package/src/javascript-file.ts +37 -0
  198. package/src/json-document.ts +241 -76
  199. package/src/keyof-comparisons.ts +3 -7
  200. package/src/kinds.ts +5 -413
  201. package/src/load/classify.ts +397 -0
  202. package/src/load/diagnostics.ts +144 -0
  203. package/src/load/discover.ts +455 -0
  204. package/src/{emit-map.ts → load/emit-map.ts} +1 -1
  205. package/src/load/expected-module.ts +188 -0
  206. package/src/load/load.ts +73 -0
  207. package/src/load/module-lookup.ts +50 -0
  208. package/src/load/plan.ts +504 -0
  209. package/src/load/specifiers.ts +168 -0
  210. package/src/load/synthesize.ts +211 -0
  211. package/src/load/test-globals.ts +251 -0
  212. package/src/load/test-joins.ts +98 -0
  213. package/src/{workspace-manifests.ts → load/workspace-manifests.ts} +5 -5
  214. package/src/{workspace-programs.ts → load/workspace-programs.ts} +127 -80
  215. package/src/{workspace-resolution.ts → load/workspace-resolution.ts} +73 -64
  216. package/src/{workspace-run.ts → load/workspace-run.ts} +18 -16
  217. package/src/{workspace.ts → load/workspace.ts} +90 -134
  218. package/src/manifest.ts +81 -75
  219. package/src/matrix.ts +154 -18
  220. package/src/mdx-entries.ts +218 -0
  221. package/src/module-declarations.ts +11 -13
  222. package/src/outside-tests.ts +1 -1
  223. package/src/overrides.ts +51 -12
  224. package/src/partial.ts +3 -2
  225. package/src/paths.ts +27 -15
  226. package/src/position.ts +2 -1
  227. package/src/print.ts +12 -91
  228. package/src/product.ts +18 -0
  229. package/src/query.ts +11 -0
  230. package/src/ref.ts +13 -0
  231. package/src/references.ts +62 -32
  232. package/src/report-schema.ts +68 -0
  233. package/src/report.ts +105 -215
  234. package/src/reporters/annotations.ts +22 -11
  235. package/src/reporters/json.ts +1 -1
  236. package/src/reporters/reporter.ts +2 -4
  237. package/src/reporters/reporters.ts +1 -1
  238. package/src/reporters/sarif.ts +29 -16
  239. package/src/reporters/template.ts +4 -20
  240. package/src/reporters/text.ts +3 -3
  241. package/src/resolve.ts +283 -1111
  242. package/src/roots.ts +490 -137
  243. package/src/run.ts +75 -91
  244. package/src/schema.ts +391 -387
  245. package/src/scope.ts +46 -138
  246. package/src/serialization-contract.ts +818 -26
  247. package/src/session.ts +77 -54
  248. package/src/source-files.ts +67 -17
  249. package/src/suppress-file.ts +36 -34
  250. package/src/suppress-inline.ts +20 -3
  251. package/src/suppress.ts +52 -63
  252. package/src/sweep.ts +53 -18
  253. package/src/symbol-keys.ts +131 -7
  254. package/src/template-field.ts +15 -25
  255. package/src/test-support.ts +155 -18
  256. package/src/text/compare.ts +27 -0
  257. package/src/text/glob.ts +210 -0
  258. package/src/text/named-files.inputs.json +1522 -0
  259. package/src/text/named-files.ts +68 -0
  260. package/src/text/shell.ts +161 -0
  261. package/src/text/yaml.ts +423 -0
  262. package/src/type-errors.ts +35 -273
  263. package/src/type-parameter-reads.ts +227 -0
  264. package/src/unseen-loads.ts +134 -0
  265. package/src/unwrap.ts +34 -0
  266. package/src/usage.ts +10 -0
  267. package/src/verbs/analyze.ts +245 -161
  268. package/src/verbs/describe.ts +14 -15
  269. package/src/verbs/explain.ts +15 -13
  270. package/src/verbs/print-config.ts +2 -1
  271. package/src/verbs/print-projects.ts +6 -4
  272. package/src/verbs/print-retained.ts +4 -2
  273. package/src/verbs/print-roots.ts +4 -2
  274. package/src/verbs/verb.ts +2 -8
  275. package/src/verbs/version.ts +15 -3
  276. package/src/workflow-steps.ts +149 -34
  277. package/dist/src/discover.js +0 -347
  278. package/dist/src/glob.js +0 -65
  279. package/dist/src/pnpm-workspace.js +0 -120
  280. package/dist/src/setup-failure.js +0 -23
  281. package/dist/src/test-joins.js +0 -101
  282. package/dist/src/version.js +0 -7
  283. package/src/discover.ts +0 -510
  284. package/src/glob.ts +0 -67
  285. package/src/pnpm-workspace.ts +0 -135
  286. package/src/setup-failure.ts +0 -39
  287. package/src/test-joins.ts +0 -120
  288. package/src/version.ts +0 -7
@@ -1,18 +1,24 @@
1
+ import { CONTRACT_VERSION, EXIT_CLEAN } from "../contract/contract.generated.js";
1
2
  import { runAnalysis, runBaselineWrite, unansweredCounts, } from "../analysis.js";
2
- import { ConfigError, kindOf } from "../config.js";
3
+ import { kindOf } from "../config.js";
3
4
  import { CONFORMANCE, DECLARED_GAPS } from "../conformance.js";
4
- import { moduleIdentity } from "../consumers.js";
5
5
  import { analyzerProvenance, verdictOf } from "../findings-pass.js";
6
- import { joinPath, normalizePath, relativePath, resolvePath } from "../paths.js";
6
+ import { dirnamePath, joinPath, normalizePath, relativePath, resolvePath } from "../paths.js";
7
+ import { moduleIdentity } from "../load/discover.js";
7
8
  import { partialNotes } from "../partial.js";
8
- import { buildReport, LANGUAGE, capFindings, sortFindings, } from "../report.js";
9
+ import { buildReport, capFindings, sortFindings, } from "../report.js";
10
+ import { reportRefusals } from "../report-schema.js";
9
11
  import { json } from "../reporters/json.js";
10
12
  import { RENDERINGS } from "../reporters/reporters.js";
11
13
  import { parseTemplate, TemplateError } from "../reporters/template.js";
12
14
  import { resolve } from "../resolve.js";
13
15
  import { otherSchemeRows, rowReason, writeBaseline } from "../suppress-file.js";
14
- import { CONTRACT_VERSION } from "../version.js";
15
- import { EXIT_CLEAN, EXIT_FAILURE } from "./verb.js";
16
+ import {} from "./verb.js";
17
+ import { UsageError } from "../usage.js";
18
+ import { bytewise } from "../text/compare.js";
19
+ import { productFault, failureExit } from "../failure.js";
20
+ import { diagnose, message } from "../product.js";
21
+ import { ownVersion } from "./version.js";
16
22
  /** The options `analyze` takes beside the ones every verb takes. */
17
23
  export const ANALYZE_OPTIONS = {
18
24
  plain: ["report", "baseline-write", "exit-code", "template"],
@@ -21,16 +27,9 @@ export const ANALYZE_OPTIONS = {
21
27
  /** The two values `--exit-code` takes; on, the default, puts the run's verdict in the exit code. */
22
28
  const EXIT_CODE_ON = "on";
23
29
  const EXIT_CODE_OFF = "off";
24
- /** A path of the run no report can name, which ends the run with the failure code. */
25
- class ReportPathError extends Error {
26
- constructor(message) {
27
- super(message);
28
- this.name = "ReportPathError";
29
- }
30
- }
31
30
  /** The formats this analyzer renders, for a message that names them. */
32
31
  function formatNames() {
33
- return [...RENDERINGS.keys()].sort().join(", ");
32
+ return [...RENDERINGS.keys()].sort(bytewise).join(", ");
34
33
  }
35
34
  /** The renderings one invocation writes: the ones it named, else the configuration's. */
36
35
  function formatsOf(named, configured) {
@@ -38,10 +37,10 @@ function formatsOf(named, configured) {
38
37
  const seen = new Set();
39
38
  for (const format of formats) {
40
39
  if (!RENDERINGS.has(format)) {
41
- throw new ConfigError("malformed", "", `${JSON.stringify(format)} is not a format this analyzer renders: the formats are ${formatNames()}`);
40
+ throw new UsageError(`${JSON.stringify(format)} is not a format this analyzer renders: the formats are ${formatNames()}`);
42
41
  }
43
42
  if (seen.has(format)) {
44
- throw new ConfigError("malformed", "", `the format ${JSON.stringify(format)} is named twice`);
43
+ throw new UsageError(`the format ${JSON.stringify(format)} is named twice`);
45
44
  }
46
45
  seen.add(format);
47
46
  }
@@ -58,16 +57,80 @@ function runRelative(invoked, path) {
58
57
  }
59
58
  const below = relativePath(invoked, path);
60
59
  if (below === undefined) {
61
- throw new ReportPathError(`a report names its target relative to the directory the run was invoked from, and ${invoked} does not contain ${path}: run from a directory that does`);
60
+ throw failureExit("unreportable-path", `a report names its target relative to the directory the run was invoked from, and ${invoked} does not contain ${path}: run from a directory that does`);
62
61
  }
63
62
  return below;
64
63
  }
64
+ /**
65
+ * One note per manifest entry the run reads back to no source file: what the entry names
66
+ * reaches nothing, so the findings its file would have rooted are reported.
67
+ */
68
+ function unmappedNotes(entries, targetRoot) {
69
+ return entries.map((entry) => {
70
+ const named = relativePath(targetRoot, entry.path) ?? entry.path;
71
+ return {
72
+ kind: "unmapped-entry",
73
+ path: relativePath(targetRoot, entry.dir) ?? ".",
74
+ key: "ts.entry_files",
75
+ message: `the manifest's ${entry.member} names ${named}, which reads back to no source file of the target: name the file it is built from in ts.entry_files`,
76
+ };
77
+ });
78
+ }
79
+ /**
80
+ * One note per load of a production file the run cannot resolve, each site once: a file
81
+ * it loads is a root the run does not see, so `ts.roots_complete` lifts no cap there.
82
+ */
83
+ function unseenLoadNotes(loads) {
84
+ return [
85
+ ...new Map(loads.map((load) => {
86
+ const { path, line, column } = load.position;
87
+ const site = `${path}:${String(line)}:${String(column)}`;
88
+ const note = {
89
+ kind: "computed-load",
90
+ path: dirnamePath(path),
91
+ message: `${site} loads a module by a computed path the analysis cannot resolve, so the configurations compiling it report what no root reaches at probable at most, whatever ts.roots_complete says`,
92
+ };
93
+ return [site, note];
94
+ })).values(),
95
+ ];
96
+ }
97
+ /** One note per package whose command strings name files a configuration holds, naming every such file. */
98
+ function heldScriptNotes(held, targetRoot) {
99
+ const files = new Map();
100
+ for (const one of held) {
101
+ files.set(one.dir, new Set([...(files.get(one.dir) ?? []), ...one.files]));
102
+ }
103
+ return [...files].map(([dir, paths]) => ({
104
+ kind: "unread-command",
105
+ path: relativePath(targetRoot, dir) ?? ".",
106
+ message: `commands the analysis does not read name ${[...paths].sort(bytewise).join(", ")}, so no finding is reported about ${paths.size === 1 ? "that file itself or the names it exports" : "those files themselves or the names they export"}`,
107
+ }));
108
+ }
109
+ function unresolvedNotes(specifiers) {
110
+ return specifiers.map(({ specifier, position }) => ({
111
+ kind: "unresolved-specifier",
112
+ path: dirnamePath(position.path),
113
+ message: `${position.path}:${String(position.line)}:${String(position.column)} loads ${JSON.stringify(specifier)}, which resolves to no file, so it references nothing`,
114
+ }));
115
+ }
116
+ function unreadLine(input, targetRoot) {
117
+ switch (input.kind) {
118
+ case "manifest": {
119
+ const path = relativePath(targetRoot, input.manifest) ?? input.manifest;
120
+ return input.reason === undefined
121
+ ? `${path} does not parse, so the manifest facts of the program formed for its package are unanswered: correct the manifest`
122
+ : `${path} cannot be read, so the manifest facts of the program formed for its package are unanswered: give the run read access to it: ${input.reason}`;
123
+ }
124
+ case "ignore-file":
125
+ return `${relativePath(targetRoot, input.path) ?? input.path} cannot be read, so the JavaScript files it would ignore are analyzed: ${input.reason}`;
126
+ }
127
+ }
65
128
  /** Each project the run dropped as a report names it, by its configuration file below the target. */
66
129
  function notBuiltOf(dropped, targetRoot) {
67
130
  return dropped.map((one) => {
68
131
  const project = relativePath(targetRoot, one.configFile);
69
132
  if (project === undefined) {
70
- throw new ReportPathError(`the project ${one.id} would be opened from ${one.configFile}, which is not below the target ${targetRoot}, so no report can name it`);
133
+ throw failureExit("unreportable-path", `the project ${one.id} would be opened from ${one.configFile}, which is not below the target ${targetRoot}, so no report can name it: analyze a target that holds it`);
71
134
  }
72
135
  return { id: one.id, project, error: one.error };
73
136
  });
@@ -77,11 +140,24 @@ function configurationsOf(projects, targetRoot) {
77
140
  return projects.map((one) => {
78
141
  const project = relativePath(targetRoot, one.configFile);
79
142
  if (project === undefined) {
80
- throw new ReportPathError(`the project ${one.id} is opened from ${one.configFile}, which is not below the target ${targetRoot}, so no report can name it`);
143
+ throw failureExit("unreportable-path", `the project ${one.id} is opened from ${one.configFile}, which is not below the target ${targetRoot}, so no report can name it: analyze a target that holds it`);
81
144
  }
82
145
  return { id: one.id, project };
83
146
  });
84
147
  }
148
+ /**
149
+ * Writes one document the run was asked for. A document that cannot be produced or written
150
+ * ends the run with the run failure that names it and `fix`, the documents written before it
151
+ * kept.
152
+ */
153
+ function writeDocument(host, path, fix, produce) {
154
+ try {
155
+ host.writeDocument(path, produce());
156
+ }
157
+ catch (error) {
158
+ throw failureExit("unwritten-output", `${path}: ${message(error)}: ${fix}`);
159
+ }
160
+ }
85
161
  /** A count with its noun, so a message reads for one record as well as for several. */
86
162
  function counted(n, noun) {
87
163
  return `${String(n)} ${noun}${n === 1 ? "" : "s"}`;
@@ -94,7 +170,7 @@ function counted(n, noun) {
94
170
  function templateOf(host, invoked, named, formats) {
95
171
  if (named === undefined || named === "") {
96
172
  if (formats.includes("template")) {
97
- throw new ConfigError("malformed", "", "the template format renders the template --template names, and none was named");
173
+ throw new UsageError("the template format renders the template --template names, and none was named");
98
174
  }
99
175
  return undefined;
100
176
  }
@@ -103,7 +179,7 @@ function templateOf(host, invoked, named, formats) {
103
179
  source = host.readFile(resolvePath(invoked, named));
104
180
  }
105
181
  catch (error) {
106
- throw new ConfigError("malformed", "", `--template=${named}: ${error instanceof Error ? error.message : String(error)}`);
182
+ throw new UsageError(`--template=${named}: ${message(error)}`);
107
183
  }
108
184
  try {
109
185
  return parseTemplate(source);
@@ -112,7 +188,7 @@ function templateOf(host, invoked, named, formats) {
112
188
  if (!(error instanceof TemplateError)) {
113
189
  throw error;
114
190
  }
115
- throw new ConfigError("malformed", "", `--template=${named}: ${error.message}`);
191
+ throw new UsageError(`--template=${named}: ${error.message}`);
116
192
  }
117
193
  }
118
194
  /**
@@ -126,17 +202,13 @@ function templateOf(host, invoked, named, formats) {
126
202
  export const analyzeVerb = ({ err, host, inputs, scope, openClient, option, repeated }) => {
127
203
  const reportPath = option("report");
128
204
  if (reportPath === undefined || reportPath === "") {
129
- throw new ConfigError("malformed", "", "analyze writes its report to the path --report names, and no path was named");
205
+ throw new UsageError("analyze writes its report to the path --report names, and no path was named");
130
206
  }
131
207
  const exitCode = option("exit-code") ?? EXIT_CODE_ON;
132
208
  if (exitCode !== EXIT_CODE_ON && exitCode !== EXIT_CODE_OFF) {
133
- throw new ConfigError("malformed", "", `--exit-code=${JSON.stringify(exitCode)}: the values are ${EXIT_CODE_ON} and ${EXIT_CODE_OFF}`);
209
+ throw new UsageError(`--exit-code=${JSON.stringify(exitCode)}: the values are ${EXIT_CODE_ON} and ${EXIT_CODE_OFF}`);
134
210
  }
135
211
  const { config, provenance } = resolve(inputs());
136
- const kind = config.targetKind;
137
- if (kind === "") {
138
- throw new ConfigError("missing-target-kind", "target.kind", "target.kind is not set");
139
- }
140
212
  const invoked = host.workingDirectory();
141
213
  const baseline = option("baseline-write");
142
214
  const documents = {
@@ -147,122 +219,106 @@ export const analyzeVerb = ({ err, host, inputs, scope, openClient, option, repe
147
219
  const template = templateOf(host, invoked, option("template"), documents.formats);
148
220
  const scoped = scope();
149
221
  const targetRoot = scoped.target.path;
150
- let version;
151
- try {
152
- version = host.analyzerVersion();
153
- }
154
- catch (error) {
155
- err.write(`deadset-ts: ${error instanceof Error ? error.message : String(error)}\n`);
156
- return EXIT_FAILURE;
157
- }
158
- let report;
222
+ const version = ownVersion(host);
159
223
  let recorded;
160
- let verdict;
161
- let partial;
162
- let warnings;
163
- let unread;
164
- let unfound;
165
- try {
166
- const root = runRelative(invoked, targetRoot);
167
- const mode = { production: true };
168
- let analysis;
169
- if (documents.baseline === undefined) {
170
- analysis = runAnalysis(openClient(config), host, scoped, config, provenance, mode);
171
- recorded = [];
172
- }
173
- else {
174
- const reason = rowReason(analyzerProvenance(version));
175
- const write = runBaselineWrite(openClient(config), host, scoped, config, provenance, mode, reason);
176
- analysis = write.first;
177
- recorded = write.rows;
178
- }
179
- const { result, run } = analysis;
180
- warnings = run.componentWarnings;
181
- unread = run.componentsUnread.map(({ configFile, reason }) => `${relativePath(resolvePath(invoked, targetRoot), configFile) ?? configFile}: its component files are not read: ${reason}`);
182
- unfound = run.librariesUnfound.map(({ configFile, error }) => `${relativePath(resolvePath(invoked, targetRoot), configFile) ?? configFile}: ${error}: the configuration is analyzed without that library`);
183
- partial = partialNotes({
184
- notBuilt: run.notBuilt,
185
- unanswered: run.unanswered,
186
- targetRoot: resolvePath(invoked, targetRoot),
187
- });
188
- const built = buildReport({
189
- contractVersion: CONTRACT_VERSION,
190
- version,
191
- conformance: CONFORMANCE,
192
- declaredGaps: DECLARED_GAPS,
193
- target: {
194
- kind: kindOf(kind, LANGUAGE),
195
- root,
196
- identity: moduleIdentity(host, scoped.target),
197
- },
198
- configurations: configurationsOf(run.projects, targetRoot),
199
- notBuilt: notBuiltOf(run.notBuilt, targetRoot),
200
- loaded: run.consumers.map((consumer) => ({
201
- id: consumer.id,
202
- path: runRelative(invoked, consumer.path),
203
- })),
204
- unavailable: [],
205
- result,
206
- testFileRules: run.testFileRules,
207
- typeErrorSkips: run.typeErrorSkips,
208
- unanswered: unansweredCounts(analysis),
209
- conventionsApplied: run.conventionsApplied,
210
- });
211
- report = capFindings(sortFindings(built, config.reporters.sort), config.reporters.maxFindings);
212
- verdict = verdictOf(result, config);
224
+ const root = runRelative(invoked, targetRoot);
225
+ const mode = { production: true };
226
+ let analysis;
227
+ if (documents.baseline === undefined) {
228
+ analysis = runAnalysis(openClient(config), host, scoped, config, provenance, mode);
229
+ recorded = [];
213
230
  }
214
- catch (error) {
215
- if (!(error instanceof ReportPathError)) {
216
- throw error;
217
- }
218
- err.write(`deadset-ts: ${error.message}\n`);
219
- return EXIT_FAILURE;
231
+ else {
232
+ const reason = rowReason(analyzerProvenance(version));
233
+ const write = runBaselineWrite(openClient(config), host, scoped, config, provenance, mode, reason);
234
+ analysis = write.first;
235
+ recorded = write.rows;
220
236
  }
221
- try {
222
- host.writeDocument(documents.report, json(report));
223
- const options = {
224
- failOn: config.reporters.failOn,
225
- readSource: (path) => host.readFile(joinPath(targetRoot, path)),
226
- template,
227
- };
228
- for (const format of documents.formats) {
229
- const rendering = RENDERINGS.get(format);
230
- if (rendering !== undefined) {
231
- host.writeDocument(documents.report + rendering.suffix, rendering.render(report, options));
232
- }
233
- }
234
- if (documents.baseline !== undefined) {
235
- const kept = host.kindOf(documents.baseline) === "file"
236
- ? otherSchemeRows(host.readFile(documents.baseline))
237
- : [];
238
- host.writeDocument(documents.baseline, writeBaseline(recorded, analyzerProvenance(version), kept));
237
+ const { result, run } = analysis;
238
+ const warnings = run.componentWarnings;
239
+ const unread = run.componentsUnread.map(({ configFile, reason }) => `${relativePath(resolvePath(invoked, targetRoot), configFile) ?? configFile}: its component files are not read: ${reason}`);
240
+ const unfound = run.librariesUnfound.map(({ configFile, error }) => `${relativePath(resolvePath(invoked, targetRoot), configFile) ?? configFile}: ${error}: the configuration is analyzed without that library`);
241
+ const unreadInputs = run.unread.map((one) => unreadLine(one, resolvePath(invoked, targetRoot)));
242
+ const partial = partialNotes({
243
+ notBuilt: run.notBuilt,
244
+ unanswered: run.unanswered,
245
+ targetRoot: resolvePath(invoked, targetRoot),
246
+ });
247
+ const built = buildReport({
248
+ contractVersion: CONTRACT_VERSION,
249
+ version,
250
+ conformance: CONFORMANCE,
251
+ declaredGaps: DECLARED_GAPS,
252
+ target: {
253
+ kind: kindOf(config.target.kind),
254
+ root,
255
+ identity: moduleIdentity(host, scoped.target),
256
+ },
257
+ configurations: configurationsOf(run.projects, targetRoot),
258
+ notBuilt: notBuiltOf(run.notBuilt, targetRoot),
259
+ loaded: run.consumers.map((consumer) => ({
260
+ id: consumer.id,
261
+ path: runRelative(invoked, consumer.path),
262
+ })),
263
+ unavailable: [],
264
+ result,
265
+ testFileRules: run.testFileRules,
266
+ typeErrorSkips: run.typeErrorSkips,
267
+ unanswered: unansweredCounts(analysis),
268
+ conventionsApplied: run.conventionsApplied,
269
+ listsComponents: config.reporters.cascade === "full",
270
+ notes: [
271
+ ...unmappedNotes(run.unmappedEntries, resolvePath(invoked, targetRoot)),
272
+ ...unseenLoadNotes(run.unseenLoads),
273
+ ...unresolvedNotes(run.unresolvedSpecifiers),
274
+ ...heldScriptNotes(run.heldScripts, resolvePath(invoked, targetRoot)),
275
+ ],
276
+ });
277
+ const report = capFindings(sortFindings(built, config.reporters.sort), config.reporters.max_findings);
278
+ const verdict = verdictOf(result, config);
279
+ const [refused] = reportRefusals(report);
280
+ if (refused !== undefined) {
281
+ throw productFault(`built a report that breaks the report schema at ${refused.pointer || "the document"}: ${refused.keyword}: ${refused.reason}`);
282
+ }
283
+ writeDocument(host, documents.report, "name a path the run can write", () => json(report));
284
+ const options = {
285
+ readSource: (path) => host.readFile(joinPath(targetRoot, path)),
286
+ template,
287
+ };
288
+ for (const format of documents.formats) {
289
+ const rendering = RENDERINGS.get(format);
290
+ if (rendering !== undefined) {
291
+ writeDocument(host, documents.report + rendering.suffix, "name a path the run can write, or correct the template that renders it", () => rendering.render(report, options));
239
292
  }
240
293
  }
241
- catch (error) {
242
- err.write(`deadset-ts: ${error instanceof Error ? error.message : String(error)}\n`);
243
- return EXIT_FAILURE;
294
+ const baselinePath = documents.baseline;
295
+ if (baselinePath !== undefined) {
296
+ writeDocument(host, baselinePath, "name a path the run can write, or repair the rows of the baseline the run would keep", () => {
297
+ const kept = host.kindOf(baselinePath) === "file" ? otherSchemeRows(host.readFile(baselinePath)) : [];
298
+ return writeBaseline(recorded, analyzerProvenance(version), kept);
299
+ });
244
300
  }
245
301
  for (const note of partial) {
246
- err.write(`deadset-ts: ${note}\n`);
302
+ diagnose(err, note);
247
303
  }
248
- for (const line of [...unread, ...unfound]) {
249
- err.write(`deadset-ts: ${line}\n`);
304
+ for (const line of [...unread, ...unfound, ...unreadInputs]) {
305
+ diagnose(err, line);
250
306
  }
251
307
  for (const warning of warnings) {
252
- err.write(`deadset-ts: ${warning.path}:${String(warning.line)}: a <script> start tag that begins a line is not read as a block: ${warning.reason}\n`);
308
+ diagnose(err, `${warning.path}:${String(warning.line)}: a <script> start tag that begins a line is not read as a block: ${warning.reason}`);
253
309
  }
254
310
  for (const skip of report.type_error_skips) {
255
- err.write(`deadset-ts: ${skip.path}:${String(skip.line)}: ${skip.message}: the function or statement holding this type error is not evaluated\n`);
311
+ diagnose(err, `${skip.path}:${String(skip.line)}: ${skip.message}: the function or statement holding this type error is not evaluated`);
256
312
  }
257
313
  if (report.totals.pending > 0) {
258
- err.write(`deadset-ts: ${counted(report.totals.pending, "pending finding")}: the report names a declared cross-language edge, and no merge has resolved it\n`);
314
+ diagnose(err, `${counted(report.totals.pending, "pending finding")}: the report names a declared cross-language edge, and no merge has resolved it`);
259
315
  }
260
316
  if (report.totals.stale_suppressions > 0) {
261
- err.write(`deadset-ts: ${counted(report.totals.stale_suppressions, "stale suppression")}\n`);
317
+ diagnose(err, counted(report.totals.stale_suppressions, "stale suppression"));
262
318
  }
263
319
  if (exitCode === EXIT_CODE_OFF) {
264
320
  if (verdict !== EXIT_CLEAN) {
265
- err.write(`deadset-ts: the exit code is configured off: the verdict of this run is ${String(verdict)}\n`);
321
+ diagnose(err, `the exit code is configured off: the verdict of this run is ${String(verdict)}`);
266
322
  }
267
323
  return EXIT_CLEAN;
268
324
  }
@@ -1,7 +1,8 @@
1
+ import { CONTRACT_VERSION, EXIT_CLEAN, EXIT_USAGE, SCHEMA_VERSIONS, } from "../contract/contract.generated.js";
1
2
  import { CONFORMANCE } from "../conformance.js";
2
- import { ANALYZER_NAME, LANGUAGE, SCHEMA_VERSIONS_ACCEPTED } from "../report.js";
3
- import { CONTRACT_VERSION } from "../version.js";
4
- import { EXIT_CLEAN, EXIT_FAILURE, EXIT_USAGE } from "./verb.js";
3
+ import {} from "./verb.js";
4
+ import { diagnose, LANGUAGE, PRODUCT } from "../product.js";
5
+ import { ownVersion } from "./version.js";
5
6
  /**
6
7
  * The document `describe` writes: the analyzer, the Contract version it implements, the
7
8
  * report schema versions it reads, the languages it claims, and its recorded result over
@@ -9,10 +10,10 @@ import { EXIT_CLEAN, EXIT_FAILURE, EXIT_USAGE } from "./verb.js";
9
10
  */
10
11
  export function describeDocument(version, recorded) {
11
12
  const document = {
12
- name: ANALYZER_NAME,
13
+ name: PRODUCT,
13
14
  version,
14
15
  contract_version: CONTRACT_VERSION,
15
- schema_versions_accepted: SCHEMA_VERSIONS_ACCEPTED,
16
+ schema_versions_accepted: SCHEMA_VERSIONS,
16
17
  languages: [LANGUAGE],
17
18
  ...(recorded === undefined
18
19
  ? {}
@@ -26,20 +27,12 @@ export function describeDocument(version, recorded) {
26
27
  };
27
28
  return `${JSON.stringify(document, null, 2)}\n`;
28
29
  }
29
- /** Writes this analyzer's description to the output stream, and nothing to the error stream. */
30
+ /** Writes this analyzer's description to the output stream. */
30
31
  export const describeVerb = ({ out, err, host, args }) => {
31
32
  if (args.length > 0) {
32
- err.write(`deadset-ts: describe takes no argument, got ${JSON.stringify(args[0])}\n`);
33
+ diagnose(err, `describe takes no argument, got ${JSON.stringify(args[0])}`);
33
34
  return EXIT_USAGE;
34
35
  }
35
- let version;
36
- try {
37
- version = host.analyzerVersion();
38
- }
39
- catch (error) {
40
- err.write(`deadset-ts: describe: ${error instanceof Error ? error.message : String(error)}\n`);
41
- return EXIT_FAILURE;
42
- }
43
- out.write(describeDocument(version, CONFORMANCE));
36
+ out.write(describeDocument(ownVersion(host), CONFORMANCE));
44
37
  return EXIT_CLEAN;
45
38
  };
@@ -1,13 +1,16 @@
1
+ import { EXIT_CLEAN, EXIT_USAGE } from "../contract/contract.generated.js";
1
2
  import { runAnalysis } from "../analysis.js";
2
3
  import { listing } from "../components.js";
3
- import { ConfigError } from "../config.js";
4
4
  import { OUTSIDE, swept as judged } from "../graph.js";
5
5
  import { referenceKey } from "../matrix.js";
6
6
  import { partialNotes } from "../partial.js";
7
7
  import { resolvePath } from "../paths.js";
8
8
  import { positionKey } from "../position.js";
9
9
  import { resolve } from "../resolve.js";
10
- import { EXIT_CLEAN, EXIT_USAGE } from "./verb.js";
10
+ import {} from "./verb.js";
11
+ import { UsageError } from "../usage.js";
12
+ import { bytewise } from "../text/compare.js";
13
+ import { diagnose } from "../product.js";
11
14
  /**
12
15
  * The three spellings of an explanation request, each naming the symbol to explain. They are
13
16
  * one request, because exactly one state holds for a symbol and the answer is that state.
@@ -33,10 +36,10 @@ function namedSymbol(option) {
33
36
  });
34
37
  const [only, ...more] = named;
35
38
  if (only === undefined) {
36
- throw new ConfigError("malformed", "", "explain explains the symbol --why, --why-live or --why-not names, and none was named");
39
+ throw new UsageError("explain explains the symbol --why, --why-live or --why-not names, and none was named");
37
40
  }
38
41
  if (more.length > 0) {
39
- throw new ConfigError("malformed", "", `explain explains one symbol, and ${named.map((one) => `--${one.name}`).join(", ")} each name one`);
42
+ throw new UsageError(`explain explains one symbol, and ${named.map((one) => `--${one.name}`).join(", ")} each name one`);
40
43
  }
41
44
  return only.value;
42
45
  }
@@ -73,7 +76,7 @@ function subjectOf(symbols, named) {
73
76
  const partial = symbols
74
77
  .filter((symbol) => symbol.ref.toLowerCase().includes(folded) || symbol.name.toLowerCase().includes(folded))
75
78
  .map(described)
76
- .sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
79
+ .sort(bytewise);
77
80
  return { candidates: partial.slice(0, MAX_PARTIAL_MATCHES) };
78
81
  }
79
82
  /** Every reference of the run once, a reference several configurations make counted once. */
@@ -257,11 +260,13 @@ function reported(found) {
257
260
  /**
258
261
  * Every finding of the run that names the declaration by its reference and reports at
259
262
  * another position: a part of it, or a suppression record naming it. Each is published under
260
- * the reference asked about, so an explanation leaving it out would disagree with the report.
263
+ * the reference asked about, or a parameter's under one it starts, so an explanation leaving
264
+ * it out would disagree with the report.
261
265
  */
262
266
  function namedElsewhere(findings, subject) {
263
267
  return findings
264
- .filter((found) => found.symbol.ref === subject.ref && positionKey(found.position) !== subject.id)
268
+ .filter((found) => (found.symbol.holder ?? found.symbol.ref) === subject.ref &&
269
+ positionKey(found.position) !== subject.id)
265
270
  .map((found) => `also reported: ${found.code} ${found.kind}\t${positionKey(found.position)}\t${found.symbol.kind} ${found.symbol.name}\n`)
266
271
  .join("");
267
272
  }
@@ -315,7 +320,7 @@ export const explainVerb = ({ out, err, host, inputs, scope, openClient, option
315
320
  targetRoot: resolvePath(host.workingDirectory(), scoped.target.path),
316
321
  });
317
322
  if (subject === undefined) {
318
- err.write(`deadset-ts: ${JSON.stringify(named)} names no one symbol of the target\n`);
323
+ diagnose(err, `${JSON.stringify(named)} names no one symbol of the target`);
319
324
  for (const candidate of candidates) {
320
325
  err.write(` ${candidate}\n`);
321
326
  }
@@ -327,7 +332,7 @@ export const explainVerb = ({ out, err, host, inputs, scope, openClient, option
327
332
  out.write(explanation(analysis, subject, config.reporters.cascade));
328
333
  }
329
334
  for (const note of notes) {
330
- err.write(`deadset-ts: ${note}\n`);
335
+ diagnose(err, note);
331
336
  }
332
337
  return subject === undefined ? EXIT_USAGE : EXIT_CLEAN;
333
338
  };
@@ -1,6 +1,7 @@
1
+ import { EXIT_CLEAN } from "../contract/contract.generated.js";
1
2
  import { printConfig } from "../print.js";
2
3
  import { resolve } from "../resolve.js";
3
- import { EXIT_CLEAN } from "./verb.js";
4
+ import {} from "./verb.js";
4
5
  /** Writes the resolved configuration with the source of every setting. */
5
6
  export const printConfigVerb = ({ out, inputs }) => {
6
7
  const { config, provenance } = resolve(inputs());
@@ -1,8 +1,10 @@
1
+ import { EXIT_CLEAN } from "../contract/contract.generated.js";
1
2
  import { runProjects } from "../analysis.js";
2
3
  import { partialNotes } from "../partial.js";
3
4
  import { resolvePath } from "../paths.js";
4
- import { resolveUnkinded } from "../resolve.js";
5
- import { EXIT_CLEAN } from "./verb.js";
5
+ import { resolvePartial } from "../resolve.js";
6
+ import {} from "./verb.js";
7
+ import { diagnose } from "../product.js";
6
8
  /**
7
9
  * Writes the name of every project one run analyzes, one per line: the identifier the
8
10
  * build matrix declares for it, or, where discovery derived the project, its
@@ -11,7 +13,7 @@ import { EXIT_CLEAN } from "./verb.js";
11
13
  * instead, and one that fails the analysis fails this command the same way.
12
14
  */
13
15
  export const printProjectsVerb = ({ out, err, host, inputs, scope, openClient }) => {
14
- const config = resolveUnkinded(inputs());
16
+ const config = resolvePartial(inputs());
15
17
  const scoped = scope();
16
18
  const answer = runProjects(openClient(config), host, scoped, config);
17
19
  for (const id of answer.configurations) {
@@ -22,7 +24,7 @@ export const printProjectsVerb = ({ out, err, host, inputs, scope, openClient })
22
24
  unanswered: answer.unanswered,
23
25
  targetRoot: resolvePath(host.workingDirectory(), scoped.target.path),
24
26
  })) {
25
- err.write(`deadset-ts: ${note}\n`);
27
+ diagnose(err, note);
26
28
  }
27
29
  return EXIT_CLEAN;
28
30
  };
@@ -1,9 +1,11 @@
1
+ import { EXIT_CLEAN } from "../contract/contract.generated.js";
1
2
  import { runSweep } from "../analysis.js";
2
3
  import { retainedLines } from "../exempt.js";
3
4
  import { partialNotes } from "../partial.js";
4
5
  import { resolvePath } from "../paths.js";
5
6
  import { resolve } from "../resolve.js";
6
- import { EXIT_CLEAN } from "./verb.js";
7
+ import {} from "./verb.js";
8
+ import { diagnose } from "../product.js";
7
9
  /**
8
10
  * Writes every declaration an exemption held back in the production sweep a report is
9
11
  * built from, one per line, and nothing where no exemption held one back. One fact
@@ -26,7 +28,7 @@ export const printRetainedVerb = ({ out, err, host, inputs, scope, openClient })
26
28
  unanswered: swept.unanswered,
27
29
  targetRoot: resolvePath(host.workingDirectory(), scoped.target.path),
28
30
  })) {
29
- err.write(`deadset-ts: ${note}\n`);
31
+ diagnose(err, note);
30
32
  }
31
33
  return EXIT_CLEAN;
32
34
  };
@@ -1,8 +1,10 @@
1
+ import { EXIT_CLEAN, EXIT_FINDINGS } from "../contract/contract.generated.js";
1
2
  import { runRoots } from "../analysis.js";
2
3
  import { partialNotes } from "../partial.js";
3
4
  import { resolvePath } from "../paths.js";
4
5
  import { resolve } from "../resolve.js";
5
- import { EXIT_CLEAN, EXIT_FINDINGS } from "./verb.js";
6
+ import {} from "./verb.js";
7
+ import { diagnose } from "../product.js";
6
8
  /**
7
9
  * One root as a line: the declaration's reference, why it is a root, and the string
8
10
  * that named it, separated by tabs. A run of several configurations adds the ones
@@ -39,7 +41,7 @@ export const printRootsVerb = ({ out, err, host, inputs, scope, openClient }) =>
39
41
  unanswered: answer.unanswered,
40
42
  targetRoot: resolvePath(host.workingDirectory(), scoped.target.path),
41
43
  })) {
42
- err.write(`deadset-ts: ${note}\n`);
44
+ diagnose(err, note);
43
45
  }
44
46
  return answer.findings.length > 0 ? EXIT_FINDINGS : EXIT_CLEAN;
45
47
  };
@@ -1,5 +1 @@
1
- /** The exit codes the Contract's exit-code table names. */
2
- export const EXIT_CLEAN = 0;
3
- export const EXIT_FINDINGS = 1;
4
- export const EXIT_USAGE = 2;
5
- export const EXIT_FAILURE = 3;
1
+ export {};