@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,13 +1,20 @@
1
1
  /**
2
2
  * The generated-file class on TypeScript: every declaration in a file that marks itself
3
- * generated, or below a directory an applied convention row names as generated, is
4
- * retained, because a generator owns the file and a deletion there is undone at the next
3
+ * generated, below a directory an applied convention row names as generated, or minified,
4
+ * is retained, because a generator owns the file and a deletion there is undone at the next
5
5
  * generation.
6
6
  */
7
+ import { minified } from "./javascript-file.js";
7
8
  /** The generated-code header, matched against each line of a leading comment. */
8
9
  const HEADER_LINE = /^\/\/ Code generated .* DO NOT EDIT\.$/u;
9
10
  /** The documentation tag `@generated` as a word of a comment. */
10
11
  const GENERATED_TAG = /(?<![\w@$])@generated(?![\w$-])/u;
12
+ /** A first comment naming the tool that wrote the file. */
13
+ const GENERATED_BY = /^\/\/ Generated by \S/u;
14
+ /** The word a generator's notice holds, beside one of {@link KEEP_OUT}. */
15
+ const GENERATED_WORD = /\bgenerated\b/iu;
16
+ /** The phrases a generator's notice asks a reader not to edit the file by. */
17
+ const KEEP_OUT = /\b(?:do not edit|will be overwritten|should not make any changes)\b/iu;
11
18
  /** The comments before a text's first token, a leading hashbang line skipped. */
12
19
  function leadingComments(text) {
13
20
  const comments = [];
@@ -48,12 +55,17 @@ export function generatedByComment(text) {
48
55
  if (comments.some((one) => GENERATED_TAG.test(one))) {
49
56
  return "generated by the @generated tag its leading comments hold";
50
57
  }
58
+ const notice = comments.join("\n");
59
+ if (GENERATED_BY.test(comments[0] ?? "") ||
60
+ (GENERATED_WORD.test(notice) && KEEP_OUT.test(notice))) {
61
+ return "generated by the notice its leading comments hold";
62
+ }
51
63
  return undefined;
52
64
  }
53
65
  /**
54
66
  * Every own file of one project that is generated, by its path below the target root,
55
67
  * with the detail a retention in it names: its leading comments' mark, else the row
56
- * naming its directory as generated.
68
+ * naming its directory as generated, else its minified text.
57
69
  */
58
70
  export function generatedFilesOf(files, byRow) {
59
71
  const found = new Map();
@@ -61,7 +73,9 @@ export function generatedFilesOf(files, byRow) {
61
73
  const row = byRow.get(path);
62
74
  const detail = generatedByComment(file.text) ??
63
75
  (row === undefined
64
- ? undefined
76
+ ? minified(file.fileName, file.text)
77
+ ? "generated as a minified JavaScript file"
78
+ : undefined
65
79
  : `generated below a directory the convention row ${row} names`);
66
80
  if (detail !== undefined) {
67
81
  found.set(path, detail);
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Which files git ignores below a tree's root, read as git reads its ignore files:
3
+ * https://git-scm.com/docs/gitignore#_pattern_format
4
+ */
5
+ import { ancestors, dirnamePath, joinPath, relativePath } from "./paths.js";
6
+ import { message } from "./product.js";
7
+ import { gitignoreExpression } from "./text/glob.js";
8
+ import { repositoryOf } from "./fs/tree.js";
9
+ /** The rules one ignore file's text writes, in order. */
10
+ function rulesOf(text) {
11
+ const rules = [];
12
+ for (const raw of text.split(/\r?\n/u)) {
13
+ let line = raw.replace(/(?<!\\)\s+$/u, "");
14
+ if (line === "" || line.startsWith("#")) {
15
+ continue;
16
+ }
17
+ const negated = line.startsWith("!");
18
+ line = negated ? line.slice(1) : line;
19
+ const directoryOnly = line.endsWith("/");
20
+ line = line.replace(/\/+$/u, "");
21
+ if (line === "") {
22
+ continue;
23
+ }
24
+ // A separator at the start or in the middle anchors the pattern to the file's
25
+ // directory; with none, the pattern matches at any depth below it.
26
+ const anchored = line.includes("/");
27
+ const pattern = line.replace(/^\//u, "");
28
+ rules.push({
29
+ negated,
30
+ directoryOnly,
31
+ expression: gitignoreExpression(anchored ? pattern : `**/${pattern}`),
32
+ });
33
+ }
34
+ return rules;
35
+ }
36
+ function rulesIn(host, path, unread) {
37
+ try {
38
+ return rulesOf(host.readFile(path));
39
+ }
40
+ catch (error) {
41
+ if (host.kindOf(path) !== "absent") {
42
+ unread(path, message(error));
43
+ }
44
+ return [];
45
+ }
46
+ }
47
+ /**
48
+ * Whether git ignores one absolute path below `root`: by the repository's `info/exclude`, then
49
+ * the `.gitignore` files from its root down to the path's directory, a later pattern overriding
50
+ * an earlier one, though a file below an ignored directory stays ignored, as git cannot re-include
51
+ * it. A path outside `root` is not ignored. With no repository, the files at and below `root` are
52
+ * read; with one, the directories above `root` give patterns but are not tested. An unreadable
53
+ * ignore file ignores nothing, and `unread` is told it.
54
+ */
55
+ export function gitIgnored(host, root, unread = () => undefined) {
56
+ const found = repositoryOf(host, root);
57
+ const repository = found?.root;
58
+ const above = repository === undefined ? [] : [...ancestors(dirnamePath(root), repository)].reverse();
59
+ const excluded = found?.exclude === undefined ? [] : rulesIn(host, found.exclude, unread);
60
+ const read = new Map();
61
+ const rulesAt = (dir) => {
62
+ let rules = read.get(dir);
63
+ if (rules === undefined) {
64
+ rules = rulesIn(host, joinPath(dir, ".gitignore"), unread);
65
+ read.set(dir, rules);
66
+ }
67
+ return rules;
68
+ };
69
+ const decided = (path, directory) => {
70
+ const sources = [
71
+ ...(repository === undefined ? [] : [[repository, excluded]]),
72
+ ...[...above, ...[...ancestors(dirnamePath(path), root)].reverse()].map((dir) => [dir, rulesAt(dir)]),
73
+ ];
74
+ let ignored = false;
75
+ for (const [dir, rules] of sources) {
76
+ const below = relativePath(dir, path) ?? "";
77
+ for (const rule of rules) {
78
+ if ((directory || !rule.directoryOnly) && rule.expression.test(below)) {
79
+ ignored = !rule.negated;
80
+ }
81
+ }
82
+ }
83
+ return ignored;
84
+ };
85
+ return (path) => {
86
+ const below = relativePath(root, path);
87
+ if (below === undefined) {
88
+ return false;
89
+ }
90
+ const parts = below.split("/");
91
+ for (let count = 1; count <= parts.length; count += 1) {
92
+ const at = joinPath(root, parts.slice(0, count).join("/"));
93
+ if (decided(at, count < parts.length)) {
94
+ return true;
95
+ }
96
+ }
97
+ return false;
98
+ };
99
+ }
package/dist/src/graph.js CHANGED
@@ -34,9 +34,9 @@ const SWEPT = {
34
34
  * Whether a root of each kind names a caller, which holds it live under both relations: a
35
35
  * tool reads what it loads and what its strings name, a runtime runs a test, setup or
36
36
  * worker file, a page's module script, a command, a script or a workflow step, the manifest
37
- * names what enters the package, an alias global stands for its export, and an entry file,
38
- * a configured root and a pattern assert a caller. A library's published API only supposes
39
- * an unseen consumer, so it is live under reachability alone.
37
+ * names what enters the package, an alias global stands for its export, an outside
38
+ * declaration names a global interface merging into it, and an entry file, a configured root
39
+ * and a pattern assert a caller. A published API supposes a consumer: reachability alone.
40
40
  */
41
41
  const NAMES_A_CALLER = {
42
42
  "entry-file": true,
@@ -49,13 +49,17 @@ const NAMES_A_CALLER = {
49
49
  pattern: true,
50
50
  "type-error": true,
51
51
  "type-query-alias": true,
52
+ "global-augmentation": true,
52
53
  "configuration-file": true,
53
54
  "configuration-string": true,
55
+ "bundler-entry": true,
54
56
  "test-runner": true,
55
57
  "browser-tests": true,
56
58
  worker: true,
57
59
  "html-entry": true,
58
60
  "workflow-step": true,
61
+ "computed-import": true,
62
+ "document-import": true,
59
63
  };
60
64
  /** Whether the sweep judges a declaration of one kind. */
61
65
  export function swept(kind) {
@@ -72,7 +76,7 @@ export function namesACaller(kind) {
72
76
  * from such a declaration still counts toward its target, because reference counting
73
77
  * asks whether any declaration names the target. A root naming nothing is dropped.
74
78
  */
75
- export function graphOf(symbols, references, roots, testFiles, supportFiles = []) {
79
+ export function graphOf(symbols, references, roots, testFiles, supportFiles = [], ambient = new Set()) {
76
80
  const supports = new Set(supportFiles);
77
81
  const index = new Map(symbols.map((symbol, at) => [symbol.id, at]));
78
82
  const at = (id) => index.get(id) ?? OUTSIDE;
@@ -123,6 +127,7 @@ export function graphOf(symbols, references, roots, testFiles, supportFiles = []
123
127
  parent,
124
128
  test: symbols.map((symbol) => tests.has(symbol.position.path)),
125
129
  support: symbols.map((symbol) => supports.has(symbol.position.path)),
130
+ ambient: symbols.map((symbol) => ambient.has(symbol.id)),
126
131
  subject: symbols.map((symbol) => swept(symbol.kind)),
127
132
  exportsOf,
128
133
  rooted,
@@ -5,9 +5,9 @@
5
5
  */
6
6
  import { isExportDeclaration, isImportDeclaration, isStringLiteral, } from "@typescript/native/ast";
7
7
  import { resolveRelativeSpecifier } from "./configuration-files.js";
8
- import { dirnamePath, joinPath, relativePath, resolvePath } from "./paths.js";
9
- /** The directory no HTML file is read below. */
10
- const SKIPPED = "node_modules";
8
+ import { ancestors, dirnamePath, joinPath, resolvePath } from "./paths.js";
9
+ import { filesBelow } from "./fs/tree.js";
10
+ import { holdsManifest } from "./fs/manifest.js";
11
11
  /** A `<script` start tag, its attribute text captured. */
12
12
  const SCRIPT_TAG = /<script(?=[\s>/])([^>]*)>/giu;
13
13
  /** The end tag an inline module script's content runs to. */
@@ -20,29 +20,6 @@ const ELSEWHERE = /^(?:\/\/|[A-Za-z][A-Za-z\d+.-]*:)/u;
20
20
  const CLASSIC_TYPES = new Set(["text/javascript", "application/javascript"]);
21
21
  /** The prefixes an inline script's specifier names a file of the target with. */
22
22
  const FILE_PREFIXES = ["/", "./", "../"];
23
- /** Every HTML file below `dir`, outside every `node_modules` directory, by absolute path. */
24
- function htmlFiles(host, dir) {
25
- let entries;
26
- try {
27
- entries = host.readDirectory(dir);
28
- }
29
- catch {
30
- return [];
31
- }
32
- const found = [];
33
- for (const entry of entries) {
34
- const path = joinPath(dir, entry.name);
35
- if (entry.directory) {
36
- if (entry.name !== SKIPPED) {
37
- found.push(...htmlFiles(host, path));
38
- }
39
- }
40
- else if (entry.name.endsWith(".html")) {
41
- found.push(path);
42
- }
43
- }
44
- return found.sort();
45
- }
46
23
  /** Each attribute of one start tag's attribute text, by its lowercase name. */
47
24
  function attributes(text) {
48
25
  const found = new Map();
@@ -98,12 +75,7 @@ function scriptValues(parse, path, text) {
98
75
  }
99
76
  /** The directory of the nearest `package.json` at or above `dir`, inside `root`, else `root`. */
100
77
  function manifestDirectory(host, root, dir) {
101
- for (let at = dir; relativePath(root, at) !== undefined; at = dirnamePath(at)) {
102
- if (host.kindOf(joinPath(at, "package.json")) === "file") {
103
- return at;
104
- }
105
- }
106
- return root;
78
+ return ancestors(dir, root).find((at) => holdsManifest(host, at)) ?? root;
107
79
  }
108
80
  /**
109
81
  * The own files the scripts of every HTML file below the target root load. A value
@@ -115,7 +87,8 @@ function manifestDirectory(host, root, dir) {
115
87
  export function htmlEntries(host, targetRoot, files, parse) {
116
88
  const root = resolvePath(host.workingDirectory(), targetRoot);
117
89
  const found = [];
118
- for (const path of htmlFiles(host, root)) {
90
+ for (const below of filesBelow(host, root, (name) => name.endsWith(".html"))) {
91
+ const path = joinPath(root, below);
119
92
  let text;
120
93
  try {
121
94
  text = host.readFile(path);
@@ -0,0 +1,97 @@
1
+ /**
2
+ * The import bindings of one file: the names its import declarations bind, which only
3
+ * the file itself can read.
4
+ */
5
+ import { isExportSpecifier, isExternalModuleReference, isIdentifier, isImportDeclaration, isImportEqualsDeclaration, isJsxElement, isJsxFragment, isJsxSelfClosingElement, isNamespaceImport, SyntaxKind, } from "@typescript/native/ast";
6
+ /** The extensions of the files whose import bindings are judged: no markup can read them. */
7
+ const JUDGED = /\.(?:[mc]?ts|tsx|[mc]?js|jsx)$/u;
8
+ /** The compiler's `jsx` settings whose emit calls no factory the file must hold. */
9
+ const AUTOMATIC_RUNTIME = new Set([4, 5, "react-jsx", "react-jsxdev"]);
10
+ /** A doc comment, where a JavaScript file names the types it imports. */
11
+ const DOC_COMMENT = /\/\*\*[\s\S]*?\*\//gu;
12
+ /** The parts of a doc comment the compiler resolves names in: a `{…}` type or link, a `@see` target. */
13
+ const DOC_REFERENCE = /\{[^{}]*\}|@see\s+[A-Za-z_$][\w$.]*/gu;
14
+ /** The factory a pragma comment names: `@jsx h` or `@jsxFrag Fragment`. */
15
+ const PRAGMA = /@jsx(?:Frag)?\s+([A-Za-z_$][\w$]*)/gu;
16
+ /**
17
+ * The names one file's import declarations bind: the default, named and namespace names of
18
+ * an `import` declaration, and the name of an `import x = require()` declaration that is
19
+ * not exported. None is judged in a declaration file or a component file.
20
+ */
21
+ export function importBindings(file) {
22
+ if (file.isDeclarationFile || !JUDGED.test(file.fileName)) {
23
+ return [];
24
+ }
25
+ const found = [];
26
+ for (const statement of file.statements) {
27
+ if (isImportDeclaration(statement)) {
28
+ const clause = statement.importClause;
29
+ if (clause?.name !== undefined) {
30
+ found.push(clause.name);
31
+ }
32
+ const named = clause?.namedBindings;
33
+ if (named !== undefined && isNamespaceImport(named)) {
34
+ found.push(named.name);
35
+ }
36
+ else if (named !== undefined) {
37
+ for (const element of named.elements) {
38
+ found.push(element.name);
39
+ }
40
+ }
41
+ }
42
+ else if (isImportEqualsDeclaration(statement) &&
43
+ isExternalModuleReference(statement.moduleReference) &&
44
+ isIdentifier(statement.name) &&
45
+ !(statement.modifiers ?? []).some((modifier) => modifier.kind === SyntaxKind.ExportKeyword)) {
46
+ found.push(statement.name);
47
+ }
48
+ }
49
+ return found;
50
+ }
51
+ /** Whether one identifier names a binding in a local export, which reads it whatever it resolves to. */
52
+ export function exportsLocally(use) {
53
+ return isExportSpecifier(use.parent);
54
+ }
55
+ /**
56
+ * The names a file reads without an identifier the program resolves: each name a type, a
57
+ * link or a `@see` tag of its doc comments spells, and, where it writes JSX the compiler
58
+ * turns into factory calls, the factories the configuration or a pragma names.
59
+ */
60
+ export function implicitReads(file, options) {
61
+ const names = new Set();
62
+ for (const comment of file.text.match(DOC_COMMENT) ?? []) {
63
+ for (const reference of comment.match(DOC_REFERENCE) ?? []) {
64
+ for (const word of reference.match(/[A-Za-z_$][\w$]*/gu) ?? []) {
65
+ names.add(word);
66
+ }
67
+ }
68
+ }
69
+ if (AUTOMATIC_RUNTIME.has(options.jsx) || !writesJsx(file)) {
70
+ return names;
71
+ }
72
+ for (const factory of [options.jsxFactory, options.jsxFragmentFactory]) {
73
+ names.add(typeof factory === "string" ? (factory.split(".")[0] ?? factory) : "React");
74
+ }
75
+ for (const match of file.text.matchAll(PRAGMA)) {
76
+ if (match[1] !== undefined) {
77
+ names.add(match[1]);
78
+ }
79
+ }
80
+ return names;
81
+ }
82
+ /** Whether a file holds a JSX element or fragment. */
83
+ function writesJsx(file) {
84
+ let found = false;
85
+ const visit = (node) => {
86
+ if (found) {
87
+ return;
88
+ }
89
+ if (isJsxElement(node) || isJsxSelfClosingElement(node) || isJsxFragment(node)) {
90
+ found = true;
91
+ return;
92
+ }
93
+ node.forEachChild(visit);
94
+ };
95
+ file.forEachChild(visit);
96
+ return found;
97
+ }
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import { isBinaryExpression, isNoSubstitutionTemplateLiteral, isStringLiteral, SyntaxKind, } from "@typescript/native/ast";
7
7
  import { sourceFilesOf } from "./source-files.js";
8
+ import { bytewise } from "./text/compare.js";
8
9
  /**
9
10
  * The text of each string literal, or template literal with no substitution, written as
10
11
  * the left operand of an `in` expression in a file of the project that is no test file.
@@ -26,5 +27,5 @@ export function inOperandNames(project, targetRoot, testFiles) {
26
27
  file.forEachChild(visit);
27
28
  }
28
29
  }
29
- return [...found].sort();
30
+ return [...found].sort(bytewise);
30
31
  }
package/dist/src/index.js CHANGED
@@ -2,4 +2,4 @@ export { run, SETTING_OPTIONS } from "./run.js";
2
2
  export { DECLINED_CONVENTIONS } from "./entry-point-gaps.js";
3
3
  export { byPosition, positionKey, PositionError, renderPosition, } from "./position.js";
4
4
  export { computedComponent, isRef, nameComponent, REF_EXPRESSIONS, renderRef, } from "./ref.js";
5
- export { CONTRACT_VERSION } from "./version.js";
5
+ export { CONTRACT_VERSION } from "./contract/contract.generated.js";