@cplieger/deadset-ts 8.0.0-dev.7 → 8.0.0-dev.9

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 (137) hide show
  1. package/dist/bin/node-host.js +21 -3
  2. package/dist/src/analysis.js +94 -299
  3. package/dist/src/config.js +6 -83
  4. package/dist/src/configuration-files.js +2 -9
  5. package/dist/src/configured-declarations.js +15 -20
  6. package/dist/src/consumers.js +3 -30
  7. package/dist/src/contract/config.generated.js +544 -0
  8. package/dist/src/contract/contract.generated.js +20 -10
  9. package/dist/src/contract/report.generated.js +3 -2
  10. package/dist/src/conventions.js +3 -8
  11. package/dist/src/edges.js +36 -112
  12. package/dist/src/exempt-classes.js +0 -2
  13. package/dist/src/exempt.js +1 -1
  14. package/dist/src/failure.js +36 -0
  15. package/dist/src/findings/completion.js +5 -4
  16. package/dist/src/findings/emitters.js +1 -1
  17. package/dist/src/findings/intra-function.js +1 -1
  18. package/dist/src/findings/non-code-artifacts.js +2 -2
  19. package/dist/src/findings/unused-declarations.js +1 -1
  20. package/dist/src/findings/visibility-narrowing.js +2 -2
  21. package/dist/src/findings-pass.js +1 -1
  22. package/dist/src/framework-lifecycle.js +7 -7
  23. package/dist/src/fs/document.js +52 -0
  24. package/dist/src/fs/manifest.js +7 -0
  25. package/dist/src/injection-container.js +1 -1
  26. package/dist/src/json-document.js +194 -67
  27. package/dist/src/kinds.js +0 -7
  28. package/dist/src/load/classify.js +236 -0
  29. package/dist/src/load/diagnostics.js +79 -0
  30. package/dist/src/load/discover.js +230 -0
  31. package/dist/src/{emit-map.js → load/emit-map.js} +1 -1
  32. package/dist/src/load/expected-module.js +136 -0
  33. package/dist/src/load/load.js +22 -0
  34. package/dist/src/load/module-lookup.js +37 -0
  35. package/dist/src/load/plan.js +155 -0
  36. package/dist/src/{test-globals.js → load/test-globals.js} +51 -56
  37. package/dist/src/load/test-joins.js +82 -0
  38. package/dist/src/{workspace-manifests.js → load/workspace-manifests.js} +3 -3
  39. package/dist/src/{workspace-programs.js → load/workspace-programs.js} +37 -40
  40. package/dist/src/{workspace-resolution.js → load/workspace-resolution.js} +21 -59
  41. package/dist/src/{workspace-run.js → load/workspace-run.js} +4 -3
  42. package/dist/src/{workspace.js → load/workspace.js} +21 -17
  43. package/dist/src/outside-tests.js +1 -1
  44. package/dist/src/print.js +10 -79
  45. package/dist/src/report-schema.js +3 -224
  46. package/dist/src/resolve.js +245 -715
  47. package/dist/src/run.js +59 -72
  48. package/dist/src/schema.js +320 -344
  49. package/dist/src/scope.js +37 -113
  50. package/dist/src/serialization-contract.js +1 -1
  51. package/dist/src/session.js +22 -28
  52. package/dist/src/source-files.js +1 -1
  53. package/dist/src/suppress-file.js +15 -17
  54. package/dist/src/suppress.js +3 -3
  55. package/dist/src/template-field.js +4 -4
  56. package/dist/src/type-errors.js +11 -216
  57. package/dist/src/usage.js +10 -0
  58. package/dist/src/verbs/analyze.js +100 -122
  59. package/dist/src/verbs/describe.js +5 -12
  60. package/dist/src/verbs/explain.js +3 -3
  61. package/dist/src/verbs/print-projects.js +2 -2
  62. package/dist/src/verbs/version.js +12 -2
  63. package/jsr.json +1 -1
  64. package/package.json +1 -1
  65. package/src/analysis.ts +95 -460
  66. package/src/config.ts +31 -298
  67. package/src/configuration-files.ts +8 -10
  68. package/src/configured-declarations.ts +18 -23
  69. package/src/consumers.ts +6 -57
  70. package/src/contract/config.generated.ts +798 -0
  71. package/src/contract/contract.generated.ts +20 -10
  72. package/src/contract/report.generated.ts +3 -2
  73. package/src/conventions.ts +6 -12
  74. package/src/edges.ts +39 -124
  75. package/src/exempt-classes.ts +0 -5
  76. package/src/exempt.ts +4 -4
  77. package/src/failure.ts +63 -0
  78. package/src/findings/completion.ts +5 -6
  79. package/src/findings/emitter.ts +2 -2
  80. package/src/findings/emitters.ts +1 -1
  81. package/src/findings/intra-function.ts +1 -1
  82. package/src/findings/non-code-artifacts.ts +4 -4
  83. package/src/findings/unused-declarations.ts +1 -1
  84. package/src/findings/visibility-narrowing.ts +2 -2
  85. package/src/findings-pass.ts +3 -3
  86. package/src/framework-lifecycle.ts +7 -7
  87. package/src/fs/document.ts +70 -0
  88. package/src/fs/manifest.ts +8 -0
  89. package/src/host.ts +12 -5
  90. package/src/injection-container.ts +1 -1
  91. package/src/json-document.ts +236 -76
  92. package/src/kinds.ts +0 -8
  93. package/src/load/classify.ts +352 -0
  94. package/src/load/diagnostics.ts +141 -0
  95. package/src/load/discover.ts +378 -0
  96. package/src/{emit-map.ts → load/emit-map.ts} +1 -1
  97. package/src/load/expected-module.ts +188 -0
  98. package/src/load/load.ts +61 -0
  99. package/src/load/module-lookup.ts +50 -0
  100. package/src/load/plan.ts +258 -0
  101. package/src/{test-globals.ts → load/test-globals.ts} +59 -65
  102. package/src/load/test-joins.ts +98 -0
  103. package/src/{workspace-manifests.ts → load/workspace-manifests.ts} +4 -4
  104. package/src/{workspace-programs.ts → load/workspace-programs.ts} +59 -53
  105. package/src/{workspace-resolution.ts → load/workspace-resolution.ts} +31 -78
  106. package/src/{workspace-run.ts → load/workspace-run.ts} +14 -11
  107. package/src/{workspace.ts → load/workspace.ts} +28 -21
  108. package/src/outside-tests.ts +1 -1
  109. package/src/partial.ts +1 -1
  110. package/src/print.ts +11 -92
  111. package/src/report-schema.ts +3 -299
  112. package/src/resolve.ts +281 -1105
  113. package/src/run.ts +68 -80
  114. package/src/schema.ts +391 -389
  115. package/src/scope.ts +45 -131
  116. package/src/serialization-contract.ts +1 -1
  117. package/src/session.ts +52 -53
  118. package/src/source-files.ts +1 -1
  119. package/src/suppress-file.ts +15 -20
  120. package/src/suppress.ts +3 -3
  121. package/src/template-field.ts +10 -7
  122. package/src/type-errors.ts +18 -288
  123. package/src/usage.ts +10 -0
  124. package/src/verbs/analyze.ts +139 -157
  125. package/src/verbs/describe.ts +4 -11
  126. package/src/verbs/explain.ts +3 -7
  127. package/src/verbs/print-projects.ts +2 -2
  128. package/src/verbs/verb.ts +2 -2
  129. package/src/verbs/version.ts +13 -2
  130. package/dist/src/base-url.js +0 -18
  131. package/dist/src/discover.js +0 -374
  132. package/dist/src/setup-failure.js +0 -19
  133. package/dist/src/test-joins.js +0 -101
  134. package/src/base-url.ts +0 -24
  135. package/src/discover.ts +0 -548
  136. package/src/setup-failure.ts +0 -37
  137. package/src/test-joins.ts +0 -118
@@ -1,75 +1,18 @@
1
- import { CONTRACT_VERSION, } from "./contract/contract.generated.js";
2
- import { LANGUAGE, PRODUCT } from "./product.js";
1
+ import { SEVERITIES } from "./contract/contract.generated.js";
2
+ import { LANGUAGE } from "./product.js";
3
3
  /**
4
4
  * The name of the repository configuration at the target root, which is also the
5
5
  * document a finding about the configuration names where no document of the
6
6
  * target supplied the setting it is about.
7
7
  */
8
8
  export const REPOSITORY_DOCUMENT = "deadset.json";
9
- /** The kind a target kind setting gives one language's declarations. */
10
- export function kindOf(setting, language) {
11
- return typeof setting === "string" ? setting : setting[language];
9
+ /** The kind a target kind setting gives this analyzer's declarations. */
10
+ export function kindOf(kind) {
11
+ return typeof kind === "string" ? kind : kind[LANGUAGE];
12
12
  }
13
- /** The severities ranked, the strongest highest. */
14
- const SEVERITY_RANK = { allow: 0, warn: 1, deny: 2 };
15
13
  /** Whether a finding at one severity fails a run under the failing severity. */
16
14
  export function fails(severity, failOn) {
17
- return SEVERITY_RANK[severity] >= SEVERITY_RANK[failOn];
18
- }
19
- /**
20
- * The configuration every documented default states. `targetKind` is empty: the
21
- * field has no default and is never inferred.
22
- */
23
- export function defaultConfig() {
24
- return {
25
- contractVersion: CONTRACT_VERSION,
26
- targetKind: "",
27
- analysis: {
28
- languages: [],
29
- minConfidence: "probable",
30
- generatedFiles: "exclude",
31
- consumerTests: "test",
32
- configurations: [],
33
- matrixComplete: false,
34
- templateDirs: [],
35
- templateDelimiters: { left: "{{", right: "}}" },
36
- },
37
- consumersComplete: false,
38
- rootPatterns: [],
39
- severity: new Map(),
40
- exemptionsDisabled: [],
41
- reporters: {
42
- formats: ["text"],
43
- sort: "position",
44
- cascade: "roots",
45
- maxFindings: 0,
46
- failOn: "deny",
47
- },
48
- providers: {
49
- analyzers: [
50
- { shape: "installed", name: "deadset-go", languages: ["go"], command: "deadset-go" },
51
- { shape: "installed", name: PRODUCT, languages: [LANGUAGE], command: PRODUCT },
52
- ],
53
- },
54
- ts: {
55
- testFiles: [
56
- "**/*.test.{ts,tsx,mts,cts}",
57
- "**/*.test-d.{ts,tsx,mts,cts}",
58
- "**/*.spec-d.{ts,tsx,mts,cts}",
59
- "**/*.spec.*",
60
- "**/__tests__/**",
61
- "**/__mocks__/**",
62
- "**/test-d/**",
63
- ],
64
- entryFiles: [],
65
- componentExtensions: [".vue", ".svelte", ".astro"],
66
- disabledConventions: [],
67
- injectionRegistrations: [],
68
- lifecycleContracts: [],
69
- serializers: [],
70
- rootsComplete: false,
71
- },
72
- };
15
+ return SEVERITIES.indexOf(severity) >= SEVERITIES.indexOf(failOn);
73
16
  }
74
17
  /**
75
18
  * Renders the origin as the provenance value the Contract declares: `default`,
@@ -78,23 +21,3 @@ export function defaultConfig() {
78
21
  export function renderOrigin(origin) {
79
22
  return origin.source === "default" ? "default" : `${origin.source}: ${origin.label}`;
80
23
  }
81
- /**
82
- * Every refusal configuration resolution makes. Each maps to the usage exit
83
- * code, and each is thrown rather than returned: a refusal ends the run, and the
84
- * one caller that turns it into an exit code is the command line.
85
- */
86
- export class ConfigError extends Error {
87
- /** Which refusal this is. */
88
- kind;
89
- /**
90
- * The key or field the message names, spelled as the document spells it. It is
91
- * empty when the refusal names none.
92
- */
93
- key;
94
- constructor(kind, key, message) {
95
- super(message);
96
- this.name = "ConfigError";
97
- this.kind = kind;
98
- this.key = key;
99
- }
100
- }
@@ -11,7 +11,7 @@ import { ancestors, dirnamePath, joinPath, relativePath, resolvePath } from "./p
11
11
  import { bytewise } from "./text/compare.js";
12
12
  import { isRecord } from "./json-document.js";
13
13
  import { filesIn } from "./fs/tree.js";
14
- import { holdsManifest, inInstalledPackages, manifestAt, readJSON } from "./fs/manifest.js";
14
+ import { DEPENDENCY_SECTIONS, holdsManifest, inInstalledPackages, manifestAt, readJSON, } from "./fs/manifest.js";
15
15
  import { shellWords } from "./text/shell.js";
16
16
  /** A configuration module's name, each form with the spelling a root reports it by. */
17
17
  const MODULE_FORMS = [
@@ -24,13 +24,6 @@ const MODULE_FORMS = [
24
24
  ];
25
25
  /** A JSON configuration file's name. */
26
26
  const DOCUMENT_NAME = /^(?:[\w-]+(?:\.[\w-]+)?\.config\.json|\.[\w-]+rc(?:\.json)?)$/u;
27
- /** The manifest members a dependency is declared in. */
28
- const DEPENDENCY_MEMBERS = [
29
- "dependencies",
30
- "devDependencies",
31
- "peerDependencies",
32
- "optionalDependencies",
33
- ];
34
27
  /** The prefixes a string names a file with, relative to the file that writes it. */
35
28
  const RELATIVE_PREFIXES = ["./", "../"];
36
29
  /** The JavaScript extensions a relative specifier from a configuration file stands for TypeScript under. */
@@ -351,7 +344,7 @@ export function declaredIn(host, dir) {
351
344
  return [];
352
345
  }
353
346
  const names = new Set();
354
- for (const member of DEPENDENCY_MEMBERS) {
347
+ for (const member of DEPENDENCY_SECTIONS) {
355
348
  const section = value[member];
356
349
  if (isRecord(section)) {
357
350
  Object.keys(section).forEach((name) => names.add(name));
@@ -179,19 +179,19 @@ export function resolveEntries(project, held, entries) {
179
179
  for (const symbol of held.symbols) {
180
180
  byRef.set(symbol.ref, [...(byRef.get(symbol.ref) ?? []), symbol.id]);
181
181
  }
182
- const modules = modulesNamed(project, new Set(entries.flatMap((entry) => (entry.shape === "module" ? [entry.module] : []))));
182
+ const modules = modulesNamed(project, new Set(entries.flatMap((entry) => ("module" in entry ? [entry.module] : []))));
183
183
  return entries.map((entry) => {
184
- if (entry.shape === "symbol") {
184
+ if ("symbol" in entry) {
185
185
  return { entry, handles: new Set(), ids: new Set(byRef.get(entry.symbol) ?? []) };
186
186
  }
187
- const { components, static: isStatic } = componentsOf(entry.shape === "module" ? entry.name : entry.global);
187
+ const { components, static: isStatic } = componentsOf("module" in entry ? entry.name : entry.global);
188
188
  const [first = "", ...rest] = components;
189
189
  let start;
190
190
  if (isStatic && rest.length === 0) {
191
191
  // Only a member is static, and a path of one component names no member.
192
192
  start = undefined;
193
193
  }
194
- else if (entry.shape === "module") {
194
+ else if ("module" in entry) {
195
195
  const module = modules.get(entry.module);
196
196
  start = module === undefined ? undefined : memberOf(project, module, first, false);
197
197
  }
@@ -246,14 +246,10 @@ export function entriesAt(project, chains, nodes, resolved) {
246
246
  * program the display name the inventory gives it.
247
247
  */
248
248
  export function spelledEntry(entry, held) {
249
- switch (entry.shape) {
250
- case "symbol":
251
- return held.symbols.find((symbol) => symbol.ref === entry.symbol)?.name ?? entry.symbol;
252
- case "module":
253
- return entry.name;
254
- case "global":
255
- return entry.global;
249
+ if ("symbol" in entry) {
250
+ return held.symbols.find((symbol) => symbol.ref === entry.symbol)?.name ?? entry.symbol;
256
251
  }
252
+ return "module" in entry ? entry.name : entry.global;
257
253
  }
258
254
  /** The key under which a lifecycle contract's declarations are configured. */
259
255
  const LIFECYCLE_KEY = "ts.lifecycle_contracts";
@@ -264,11 +260,14 @@ const LIFECYCLE_KEY = "ts.lifecycle_contracts";
264
260
  */
265
261
  export function configuredDeclarations(config) {
266
262
  return [
267
- ...config.ts.injectionRegistrations.map((entry) => ({
263
+ ...config.ts.injection_registrations.map((entry) => ({
268
264
  key: "ts.injection_registrations",
269
265
  entry,
270
266
  })),
271
- ...config.ts.lifecycleContracts.flatMap((contract) => [...contract.components, ...contract.bases].map((entry) => ({ key: LIFECYCLE_KEY, entry }))),
267
+ ...config.ts.lifecycle_contracts.flatMap((contract) => [...(contract.components ?? []), ...(contract.bases ?? [])].map((entry) => ({
268
+ key: LIFECYCLE_KEY,
269
+ entry,
270
+ }))),
272
271
  ...config.ts.serializers.map((entry) => ({ key: "ts.serializers", entry })),
273
272
  ];
274
273
  }
@@ -294,12 +293,8 @@ export function declarationsNamed(project, held, configured) {
294
293
  * sign and its name, and a global entry's path after a number sign.
295
294
  */
296
295
  export function configuredRef(entry) {
297
- switch (entry.shape) {
298
- case "symbol":
299
- return entry.symbol;
300
- case "module":
301
- return `${entry.module}#${entry.name}`;
302
- case "global":
303
- return `#${entry.global}`;
296
+ if ("symbol" in entry) {
297
+ return entry.symbol;
304
298
  }
299
+ return "module" in entry ? `${entry.module}#${entry.name}` : `#${entry.global}`;
305
300
  }
@@ -1,34 +1,7 @@
1
- /**
2
- * The consumers a scope declares, loaded beside the target: each a directory on the
3
- * local filesystem whose compiler configurations open as projects of the run's one
4
- * snapshot, and whose references to the target's declarations count against them.
5
- */
6
- import { consumerProjects } from "./discover.js";
7
- import { inventory, packageScope } from "./inventory.js";
1
+ import { inventory } from "./inventory.js";
8
2
  import { relativePath } from "./paths.js";
9
3
  import { references } from "./references.js";
10
4
  import { narrowedTo } from "./session.js";
11
- /** The name one module publishes itself under: the scope's, else its manifest's. */
12
- export function moduleIdentity(host, module) {
13
- return module.id === "" ? packageScope(host, module.path)("index.ts").package : module.id;
14
- }
15
- /**
16
- * Every consumer the scope declares, in its order, with the projects it opens as. A
17
- * configuration that is also one of the target's projects, or an earlier consumer's, is
18
- * that project's alone. A consumer whose directory is absent, is no directory or holds
19
- * no configuration ends the run naming it, before any project opens.
20
- */
21
- export function consumerLoads(engine, host, scope, targetConfigFiles) {
22
- const opened = new Set(targetConfigFiles);
23
- return scope.consumers.map((module) => {
24
- const configFiles = consumerProjects(engine, host, module.path).filter((configFile) => {
25
- const fresh = !opened.has(configFile);
26
- opened.add(configFile);
27
- return fresh;
28
- });
29
- return { consumer: { id: moduleIdentity(host, module), path: module.path }, configFiles };
30
- });
31
- }
32
5
  /**
33
6
  * Every reference one consumer project's own files make to a declaration of the target.
34
7
  * The target's declarations are enumerated over the target's files the consumer's
@@ -39,10 +12,10 @@ export function consumerLoads(engine, host, scope, targetConfigFiles) {
39
12
  export function consumerReferences(project, host, targetRoot, consumer, config) {
40
13
  const held = inventory(narrowedTo(project, (file) => relativePath(targetRoot, file.fileName) !== undefined), host, targetRoot);
41
14
  const found = references(project, held, targetRoot, {
42
- testFiles: config.ts.testFiles,
15
+ testFiles: config.ts.test_files,
43
16
  consumer,
44
17
  }).references;
45
- if (config.analysis.consumerTests !== "production") {
18
+ if (config.analysis.consumer_tests !== "production") {
46
19
  return found;
47
20
  }
48
21
  return found.map((reference) => (reference.test ? { ...reference, test: false } : reference));