@cplieger/deadset-ts 8.0.0-dev.15 → 8.0.0-dev.16

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 (134) hide show
  1. package/dist/src/analysis.js +41 -37
  2. package/dist/src/commands/read.js +6 -7
  3. package/dist/src/conformance-record.js +1 -1
  4. package/dist/src/consumers.js +3 -1
  5. package/dist/src/contract/config.generated.js +1 -1
  6. package/dist/src/contract/contract.generated.js +119 -2
  7. package/dist/src/dependencies.js +79 -48
  8. package/dist/src/entries/build-scripts.js +222 -0
  9. package/dist/src/{configuration-files.js → entries/configuration-files.js} +20 -58
  10. package/dist/src/{convention-rows.js → entries/convention-rows.js} +120 -27
  11. package/dist/src/entries/conventions.js +739 -0
  12. package/dist/src/{html-entries.js → entries/html-entries.js} +3 -3
  13. package/dist/src/{mdx-entries.js → entries/mdx-entries.js} +2 -2
  14. package/dist/src/entries/run-directories.js +77 -0
  15. package/dist/src/entries/sources.js +144 -0
  16. package/dist/src/entries/static-module.js +669 -0
  17. package/dist/src/entries/test-runners.js +684 -0
  18. package/dist/src/{workflow-steps.js → entries/workflow-steps.js} +18 -8
  19. package/dist/src/extensions.js +37 -0
  20. package/dist/src/facts.js +38 -0
  21. package/dist/src/findings/emitters.js +5 -8
  22. package/dist/src/findings/self-check.js +36 -20
  23. package/dist/src/findings-pass.js +5 -6
  24. package/dist/src/framework-lifecycle.js +1 -1
  25. package/dist/src/fs/manifest.js +15 -20
  26. package/dist/src/generated-file.js +172 -29
  27. package/dist/src/graph.js +2 -4
  28. package/dist/src/index.js +1 -1
  29. package/dist/src/injection-container.js +1 -1
  30. package/dist/src/inventory/commonjs.js +62 -17
  31. package/dist/src/inventory/enumerate.js +2 -1
  32. package/dist/src/javascript-file.js +26 -11
  33. package/dist/src/load/classify.js +28 -9
  34. package/dist/src/load/diagnostics.js +8 -1
  35. package/dist/src/load/discover.js +15 -7
  36. package/dist/src/load/plan.js +2 -2
  37. package/dist/src/load/synthesize.js +5 -5
  38. package/dist/src/load/workspace-manifests.js +1 -1
  39. package/dist/src/matrix.js +6 -13
  40. package/dist/src/outside-tests.js +1 -1
  41. package/dist/src/paths.js +16 -0
  42. package/dist/src/platform-calls.js +78 -0
  43. package/dist/src/platform-symbols.js +140 -0
  44. package/dist/src/references.js +202 -32
  45. package/dist/src/resolve.js +1 -1
  46. package/dist/src/{configured-declarations.js → roots/configured-declarations.js} +4 -4
  47. package/dist/src/{entry-point-gaps.js → roots/entry-point-gaps.js} +5 -8
  48. package/dist/src/{manifest.js → roots/manifest.js} +4 -4
  49. package/dist/src/roots/published-reach.js +412 -0
  50. package/dist/src/roots/root-set.js +489 -0
  51. package/dist/src/roots/unseen-loads.js +208 -0
  52. package/dist/src/serialization-contract.js +1 -1
  53. package/dist/src/source-files.js +5 -9
  54. package/dist/src/suppress.js +30 -32
  55. package/dist/src/test-support.js +4 -2
  56. package/dist/src/verbs/analyze.js +13 -1
  57. package/dist/src/verbs/describe.js +5 -3
  58. package/jsr.json +1 -1
  59. package/package.json +2 -2
  60. package/src/analysis.ts +75 -52
  61. package/src/automatic-types.ts +1 -1
  62. package/src/commands/read.ts +6 -8
  63. package/src/conformance-record.ts +1 -1
  64. package/src/consumers.ts +4 -0
  65. package/src/contract/config.generated.ts +1 -1
  66. package/src/contract/contract.generated.ts +138 -2
  67. package/src/dependencies.ts +96 -49
  68. package/src/entries/build-scripts.ts +292 -0
  69. package/src/{configuration-files.ts → entries/configuration-files.ts} +23 -75
  70. package/src/{convention-rows.ts → entries/convention-rows.ts} +167 -28
  71. package/src/{conventions.ts → entries/conventions.ts} +347 -522
  72. package/src/{html-entries.ts → entries/html-entries.ts} +5 -5
  73. package/src/{mdx-entries.ts → entries/mdx-entries.ts} +4 -4
  74. package/src/entries/run-directories.ts +108 -0
  75. package/src/entries/sources.ts +266 -0
  76. package/src/entries/static-module.ts +857 -0
  77. package/src/entries/test-runners.ts +868 -0
  78. package/src/{workflow-steps.ts → entries/workflow-steps.ts} +29 -11
  79. package/src/exempt.ts +3 -2
  80. package/src/extensions.ts +45 -0
  81. package/src/facts.ts +44 -0
  82. package/src/file-facts.ts +1 -1
  83. package/src/findings/emitters.ts +14 -10
  84. package/src/findings/self-check.ts +41 -22
  85. package/src/findings/visibility-narrowing.ts +1 -1
  86. package/src/findings-pass.ts +5 -12
  87. package/src/framework-lifecycle.ts +1 -1
  88. package/src/fs/manifest.ts +25 -21
  89. package/src/generated-file.ts +240 -36
  90. package/src/graph.ts +3 -5
  91. package/src/index.ts +1 -1
  92. package/src/injection-container.ts +1 -1
  93. package/src/inventory/commonjs.ts +102 -17
  94. package/src/inventory/enumerate.ts +2 -1
  95. package/src/javascript-file.ts +29 -12
  96. package/src/load/classify.ts +49 -13
  97. package/src/load/diagnostics.ts +11 -1
  98. package/src/load/discover.ts +27 -11
  99. package/src/load/plan.ts +11 -2
  100. package/src/load/synthesize.ts +6 -6
  101. package/src/load/test-globals.ts +1 -1
  102. package/src/load/workspace-manifests.ts +1 -1
  103. package/src/load/workspace-run.ts +1 -1
  104. package/src/matrix.ts +7 -14
  105. package/src/outside-tests.ts +1 -1
  106. package/src/paths.ts +18 -0
  107. package/src/platform-calls.ts +119 -0
  108. package/src/platform-symbols.ts +205 -0
  109. package/src/references.ts +281 -34
  110. package/src/report.ts +1 -1
  111. package/src/resolve.ts +1 -1
  112. package/src/{configured-declarations.ts → roots/configured-declarations.ts} +7 -7
  113. package/src/{entry-point-gaps.ts → roots/entry-point-gaps.ts} +5 -8
  114. package/src/{manifest.ts → roots/manifest.ts} +5 -5
  115. package/src/roots/published-reach.ts +481 -0
  116. package/src/{roots.ts → roots/root-set.ts} +203 -630
  117. package/src/roots/unseen-loads.ts +307 -0
  118. package/src/serialization-contract.ts +1 -1
  119. package/src/source-files.ts +5 -10
  120. package/src/suppress.ts +48 -33
  121. package/src/test-support.ts +8 -3
  122. package/src/verbs/analyze.ts +17 -4
  123. package/src/verbs/describe.ts +5 -2
  124. package/src/verbs/explain.ts +1 -1
  125. package/dist/src/build-scripts.js +0 -418
  126. package/dist/src/conventions.js +0 -907
  127. package/dist/src/entry-points.js +0 -444
  128. package/dist/src/own-body.js +0 -28
  129. package/dist/src/roots.js +0 -865
  130. package/dist/src/unseen-loads.js +0 -189
  131. package/src/build-scripts.ts +0 -536
  132. package/src/entry-points.ts +0 -584
  133. package/src/own-body.ts +0 -42
  134. package/src/unseen-loads.ts +0 -282
@@ -1,282 +0,0 @@
1
- /**
2
- * The loads by a computed path: those whose files the analysis resolves, and those of a
3
- * project's production files it cannot resolve, an `import()` or `require()` call whose
4
- * path starts with no relative literal naming a directory below the calling file's. The
5
- * files such a load runs are roots the analysis does not see, so the configuration's
6
- * roots are never complete.
7
- */
8
-
9
- import {
10
- isBinaryExpression,
11
- isCallExpression,
12
- isIdentifier,
13
- isMetaProperty,
14
- isNoSubstitutionTemplateLiteral,
15
- isObjectLiteralExpression,
16
- isPropertyAccessExpression,
17
- isPropertyAssignment,
18
- isStringLiteral,
19
- isTemplateExpression,
20
- SyntaxKind,
21
- type CallExpression,
22
- type Identifier,
23
- type Node,
24
- type SourceFile,
25
- } from "@typescript/native/ast";
26
- import { literalsOf } from "./entry-points.ts";
27
- import { hasOwnBody } from "./own-body.ts";
28
- import { dirnamePath, relativePath, resolvePath } from "./paths.ts";
29
- import { renderPosition, type Position } from "./position.ts";
30
- import type { ProjectView } from "./session.ts";
31
- import { sourceFilesOf } from "./source-files.ts";
32
- import { unwrapped } from "./unwrap.ts";
33
- import { globExpression } from "./text/glob.ts";
34
-
35
- /** One load the analysis cannot resolve, in the configuration whose production file writes it. */
36
- export interface UnseenLoad {
37
- readonly configuration: string;
38
- /** The position of the call. */
39
- readonly position: Position;
40
- }
41
-
42
- /** The literal text a computed path starts with: a template's head, or a concatenation's first literal. */
43
- function leadingLiteral(node: Node): string | undefined {
44
- const at = unwrapped(node);
45
- if (isTemplateExpression(at)) {
46
- return at.head.text;
47
- }
48
- if (isBinaryExpression(at) && at.operatorToken.kind === SyntaxKind.PlusToken) {
49
- const left = unwrapped(at.left);
50
- return isStringLiteral(left) || isNoSubstitutionTemplateLiteral(left)
51
- ? left.text
52
- : leadingLiteral(at.left);
53
- }
54
- return undefined;
55
- }
56
-
57
- /**
58
- * The directory below `dir` a computed load's leading literal names, every file of which
59
- * the load reaches, or none where it names a package, `dir` itself or a directory holding
60
- * it, each of which would name every sibling.
61
- */
62
- function computedLoadDirectory(dir: string, prefix: string): string | undefined {
63
- if (!(prefix.startsWith("./") || prefix.startsWith("../")) || !prefix.endsWith("/")) {
64
- return undefined;
65
- }
66
- const target = resolvePath(dir, prefix);
67
- return target === dir || relativePath(target, dir) !== undefined ? undefined : target;
68
- }
69
-
70
- /** One `import()`, `require()` or `import.meta.glob()` call, and the declaration whose code writes it. */
71
- export interface LoadCall {
72
- readonly call: CallExpression;
73
- readonly from: string;
74
- }
75
-
76
- /** One file a computed load may load, by its id. */
77
- interface Loadable {
78
- readonly file: SourceFile;
79
- readonly fileId: string;
80
- }
81
-
82
- /** One load by a computed path whose files the analysis resolves. */
83
- interface ComputedLoad {
84
- readonly call: CallExpression;
85
- readonly from: string;
86
- /** The `require` the call names; {@link hasOwnBody} owns which one loads nothing. */
87
- readonly require: Identifier | undefined;
88
- readonly files: readonly Loadable[];
89
- /** Whether the load reads each file as text or as a URL, which references no declaration of it. */
90
- readonly asset: boolean;
91
- /**
92
- * Whether the load is an eager glob, which Vite turns into static imports at the top of
93
- * the calling module (https://vite.dev/guide/features.html#glob-import), so the file
94
- * evaluates what it loads wherever the call is written.
95
- */
96
- readonly eager: boolean;
97
- }
98
-
99
- /** Whether one node is a call that may load a module by a computed path. */
100
- export function isLoadCall(node: Node): node is CallExpression {
101
- if (!isCallExpression(node)) {
102
- return false;
103
- }
104
- const callee = node.expression;
105
- return (
106
- callee.kind === SyntaxKind.ImportKeyword ||
107
- (isIdentifier(callee) && callee.text === "require") ||
108
- isMetaGlob(node)
109
- );
110
- }
111
-
112
- /**
113
- * The resolved computed loads among one file's load calls, each loading the `candidates`
114
- * but the file itself: an `import()` or `require()` whose path starts with a relative
115
- * literal naming a directory below the file's, every candidate below it, and an
116
- * `import.meta.glob` of relative literal globs, every candidate one matches, each read
117
- * against the file's directory, as a bundler's context module reads them.
118
- */
119
- export function computedLoadsOf(
120
- file: SourceFile,
121
- calls: readonly LoadCall[],
122
- candidates: readonly Loadable[],
123
- ): readonly ComputedLoad[] {
124
- const dir = dirnamePath(file.fileName);
125
- const others = candidates.filter((candidate) => candidate.file !== file);
126
- return calls.flatMap(({ call, from }): ComputedLoad[] => {
127
- const [first, options] = call.arguments;
128
- if (first === undefined) {
129
- return [];
130
- }
131
- if (isMetaGlob(call)) {
132
- const globs = (literalsOf(first) ?? [])
133
- .filter((pattern) => pattern.startsWith("./") || pattern.startsWith("../"))
134
- .map((pattern) => globExpression(resolvePath(dir, pattern)));
135
- const files = others.filter((candidate) =>
136
- globs.some((glob) => glob.test(candidate.file.fileName)),
137
- );
138
- const asset = readsAsAsset(options);
139
- return [{ call, from, require: undefined, files, asset, eager: isEager(options) }];
140
- }
141
- const prefix = leadingLiteral(first);
142
- const target = prefix === undefined ? undefined : computedLoadDirectory(dir, prefix);
143
- if (target === undefined) {
144
- return [];
145
- }
146
- const files = others.filter(
147
- (candidate) => relativePath(target, candidate.file.fileName) !== undefined,
148
- );
149
- const callee = call.expression;
150
- const require = isIdentifier(callee) ? callee : undefined;
151
- return [{ call, from, require, files, asset: false, eager: false }];
152
- });
153
- }
154
-
155
- /** Whether one call is `import.meta.glob(...)`. */
156
- function isMetaGlob(node: CallExpression): boolean {
157
- if (!isPropertyAccessExpression(node.expression)) {
158
- return false;
159
- }
160
- const { expression, name } = node.expression;
161
- return (
162
- isIdentifier(name) &&
163
- name.text === "glob" &&
164
- isMetaProperty(expression) &&
165
- expression.keywordToken === SyntaxKind.ImportKeyword
166
- );
167
- }
168
-
169
- /** The values an `import.meta.glob` options object assigns, each by its literal key. */
170
- function globOptions(options: Node | undefined): readonly [string, Node][] {
171
- const literal = options === undefined ? undefined : unwrapped(options);
172
- if (literal === undefined || !isObjectLiteralExpression(literal)) {
173
- return [];
174
- }
175
- return literal.properties.flatMap((property): [string, Node][] =>
176
- isPropertyAssignment(property) &&
177
- (isIdentifier(property.name) || isStringLiteral(property.name))
178
- ? [[property.name.text, unwrapped(property.initializer)]]
179
- : [],
180
- );
181
- }
182
-
183
- /** Whether the options of an `import.meta.glob` set `eager` to `true`. */
184
- function isEager(options: Node | undefined): boolean {
185
- return globOptions(options).some(
186
- ([key, value]) => key === "eager" && value.kind === SyntaxKind.TrueKeyword,
187
- );
188
- }
189
-
190
- /** The query parameters that make Vite load a file as its text or its URL, each written bare. */
191
- const ASSET_QUERY = /(?:^\?|&)(?:raw|url|inline)(?:&|$)/u;
192
-
193
- /**
194
- * Whether the options of an `import.meta.glob` read each file as text or as a URL: a
195
- * `query` string holding a bare `raw`, `url` or `inline`, or an `as` of `raw` or `url`,
196
- * which Vite reads as that query (https://vite.dev/guide/features.html#glob-import). Any
197
- * other query is read as loading the module, which keeps more than it may.
198
- */
199
- function readsAsAsset(options: Node | undefined): boolean {
200
- return globOptions(options).some(([key, value]) => {
201
- if (!isStringLiteral(value) && !isNoSubstitutionTemplateLiteral(value)) {
202
- return false;
203
- }
204
- if (key === "as") {
205
- return value.text === "raw" || value.text === "url";
206
- }
207
- return (
208
- key === "query" &&
209
- ASSET_QUERY.test(value.text.startsWith("?") ? value.text : `?${value.text}`)
210
- );
211
- });
212
- }
213
-
214
- /** Whether a computed path's leading literal names a package, whose files are none of the target's. */
215
- function namesPackage(prefix: string | undefined): boolean {
216
- return (
217
- prefix !== undefined &&
218
- prefix !== "" &&
219
- !prefix.startsWith(".") &&
220
- !prefix.startsWith("/") &&
221
- !/^[A-Za-z][A-Za-z\d+.-]*:/u.test(prefix)
222
- );
223
- }
224
-
225
- /**
226
- * Every unresolved load the project's production files write, in file then source order.
227
- * `testFiles` holds the test files by their path below the target root. A `require` call
228
- * loads a module unless {@link hasOwnBody} reads it as the project's own function.
229
- */
230
- export function unseenLoadsOf<Brand>(
231
- project: ProjectView<Brand>,
232
- configuration: string,
233
- targetRoot: string,
234
- testFiles: readonly string[],
235
- ): readonly UnseenLoad[] {
236
- const tests = new Set(testFiles);
237
- const sites: { readonly position: Position; readonly require: Node | undefined }[] = [];
238
- for (const [path, file] of sourceFilesOf(project, targetRoot).byPath) {
239
- if (tests.has(path) || file.isDeclarationFile) {
240
- continue;
241
- }
242
- const dir = dirnamePath(file.fileName);
243
- const visit = (node: Node): void => {
244
- if (isCallExpression(node)) {
245
- const callee = node.expression;
246
- const required = isIdentifier(callee) && callee.text === "require";
247
- const [first] = node.arguments;
248
- const argument = first === undefined ? undefined : unwrapped(first);
249
- if (
250
- (callee.kind === SyntaxKind.ImportKeyword || required) &&
251
- argument !== undefined &&
252
- !isStringLiteral(argument) &&
253
- !isNoSubstitutionTemplateLiteral(argument)
254
- ) {
255
- const prefix = leadingLiteral(argument);
256
- const seen =
257
- namesPackage(prefix) ||
258
- (prefix !== undefined && computedLoadDirectory(dir, prefix) !== undefined);
259
- if (!seen) {
260
- sites.push({
261
- position: renderPosition(file, targetRoot, node.getStart()),
262
- require: required ? callee : undefined,
263
- });
264
- }
265
- }
266
- }
267
- node.forEachChild(visit);
268
- };
269
- file.forEachChild(visit);
270
- }
271
- const requires = sites.flatMap((site) => (site.require === undefined ? [] : [site.require]));
272
- const local = new Set<Node>();
273
- project.symbolsAt(requires.map((node) => project.handle(node))).forEach((symbol, at) => {
274
- const node = requires[at];
275
- if (node !== undefined && typeof symbol === "object" && hasOwnBody(project, symbol)) {
276
- local.add(node);
277
- }
278
- });
279
- return sites
280
- .filter((site) => site.require === undefined || !local.has(site.require))
281
- .map((site) => ({ configuration, position: site.position }));
282
- }