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

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 (207) hide show
  1. package/dist/src/alias-chain.js +0 -5
  2. package/dist/src/amd.js +81 -0
  3. package/dist/src/analysis.js +94 -54
  4. package/dist/src/augmentations.js +23 -24
  5. package/dist/src/bindings.js +382 -0
  6. package/dist/src/calls.js +25 -8
  7. package/dist/src/commands/read.js +6 -7
  8. package/dist/src/commands/tools.js +5 -9
  9. package/dist/src/component-files.js +3 -2
  10. package/dist/src/conformance-record.js +1 -1
  11. package/dist/src/consumers.js +9 -10
  12. package/dist/src/contextual-uses.js +1 -17
  13. package/dist/src/contract/config.generated.js +5 -2
  14. package/dist/src/contract/contract.generated.js +119 -2
  15. package/dist/src/contract/report.generated.js +6 -2
  16. package/dist/src/dependencies.js +98 -71
  17. package/dist/src/destructuring.js +1 -19
  18. package/dist/src/element-access.js +179 -164
  19. package/dist/src/entries/build-scripts.js +222 -0
  20. package/dist/src/{configuration-files.js → entries/configuration-files.js} +22 -64
  21. package/dist/src/{convention-rows.js → entries/convention-rows.js} +120 -27
  22. package/dist/src/entries/conventions.js +739 -0
  23. package/dist/src/{html-entries.js → entries/html-entries.js} +9 -12
  24. package/dist/src/{mdx-entries.js → entries/mdx-entries.js} +3 -3
  25. package/dist/src/entries/run-directories.js +77 -0
  26. package/dist/src/entries/sources.js +144 -0
  27. package/dist/src/entries/static-module.js +670 -0
  28. package/dist/src/entries/test-runners.js +684 -0
  29. package/dist/src/{workflow-steps.js → entries/workflow-steps.js} +18 -8
  30. package/dist/src/extensions.js +37 -0
  31. package/dist/src/facts.js +38 -0
  32. package/dist/src/findings/completion.js +40 -4
  33. package/dist/src/findings/emitters.js +5 -8
  34. package/dist/src/{implementations.js → findings/implementations.js} +3 -3
  35. package/dist/src/{in-operands.js → findings/in-operands.js} +2 -2
  36. package/dist/src/findings/self-check.js +36 -20
  37. package/dist/src/findings-pass.js +5 -6
  38. package/dist/src/framework-lifecycle.js +42 -15
  39. package/dist/src/fs/manifest.js +15 -20
  40. package/dist/src/generated-file.js +172 -29
  41. package/dist/src/graph.js +14 -8
  42. package/dist/src/import-bindings.js +73 -28
  43. package/dist/src/index/sites.js +557 -0
  44. package/dist/src/index.js +1 -1
  45. package/dist/src/indexed-access.js +523 -478
  46. package/dist/src/injection-container.js +1 -1
  47. package/dist/src/interface-satisfaction.js +1 -1
  48. package/dist/src/inventory/commonjs.js +62 -17
  49. package/dist/src/inventory/enumerate.js +2 -1
  50. package/dist/src/javascript-file.js +26 -11
  51. package/dist/src/keyof-comparisons.js +124 -103
  52. package/dist/src/load/classify.js +28 -9
  53. package/dist/src/load/diagnostics.js +8 -1
  54. package/dist/src/load/discover.js +15 -7
  55. package/dist/src/load/expected-module.js +2 -2
  56. package/dist/src/load/plan.js +2 -2
  57. package/dist/src/load/specifiers.js +2 -4
  58. package/dist/src/load/synthesize.js +10 -5
  59. package/dist/src/load/workspace-manifests.js +1 -1
  60. package/dist/src/load/workspace-resolution.js +2 -2
  61. package/dist/src/matrix.js +12 -17
  62. package/dist/src/module-declarations.js +70 -85
  63. package/dist/src/overrides.js +134 -112
  64. package/dist/src/paths.js +56 -1
  65. package/dist/src/platform-calls.js +78 -0
  66. package/dist/src/platform-symbols.js +134 -0
  67. package/dist/src/references/read-rule.js +1 -0
  68. package/dist/src/references/read-rules.js +48 -0
  69. package/dist/src/references/sink.js +151 -0
  70. package/dist/src/references/sources.js +450 -0
  71. package/dist/src/references.js +111 -1116
  72. package/dist/src/resolve.js +1 -1
  73. package/dist/src/{configured-declarations.js → roots/configured-declarations.js} +7 -4
  74. package/dist/src/{entry-point-gaps.js → roots/entry-point-gaps.js} +5 -8
  75. package/dist/src/{manifest.js → roots/manifest.js} +4 -4
  76. package/dist/src/roots/published-reach.js +412 -0
  77. package/dist/src/roots/root-set.js +489 -0
  78. package/dist/src/roots/unseen-loads.js +236 -0
  79. package/dist/src/serialization-contract.js +9 -4
  80. package/dist/src/source-files.js +5 -9
  81. package/dist/src/stores.js +4 -2
  82. package/dist/src/suppress.js +30 -32
  83. package/dist/src/sweep.js +25 -13
  84. package/dist/src/symbol-keys.js +89 -83
  85. package/dist/src/tests/file-class.js +76 -0
  86. package/dist/src/{outside-tests.js → tests/outside.js} +7 -7
  87. package/dist/src/{test-support.js → tests/support.js} +5 -12
  88. package/dist/src/type-parameter-reads.js +178 -139
  89. package/dist/src/unimplemented-callees.js +262 -242
  90. package/dist/src/verbs/analyze.js +15 -3
  91. package/dist/src/verbs/describe.js +5 -3
  92. package/dist/src/verbs/explain.js +50 -28
  93. package/dist/src/verbs/print-retained.js +2 -2
  94. package/jsr.json +1 -1
  95. package/package.json +3 -3
  96. package/src/alias-chain.ts +0 -7
  97. package/src/amd.ts +130 -0
  98. package/src/analysis.ts +156 -70
  99. package/src/augmentations.ts +41 -27
  100. package/src/automatic-types.ts +1 -1
  101. package/src/bindings.ts +460 -0
  102. package/src/calls.ts +25 -7
  103. package/src/commands/read.ts +6 -8
  104. package/src/commands/tools.ts +5 -11
  105. package/src/component-files.ts +4 -2
  106. package/src/conformance-record.ts +1 -1
  107. package/src/consumers.ts +12 -11
  108. package/src/contextual-uses.ts +2 -22
  109. package/src/contract/config.generated.ts +5 -2
  110. package/src/contract/contract.generated.ts +138 -2
  111. package/src/contract/report.generated.ts +6 -2
  112. package/src/dependencies.ts +117 -71
  113. package/src/destructuring.ts +1 -31
  114. package/src/element-access.ts +188 -182
  115. package/src/entries/build-scripts.ts +292 -0
  116. package/src/{configuration-files.ts → entries/configuration-files.ts} +33 -82
  117. package/src/{convention-rows.ts → entries/convention-rows.ts} +167 -28
  118. package/src/{conventions.ts → entries/conventions.ts} +349 -523
  119. package/src/{html-entries.ts → entries/html-entries.ts} +19 -18
  120. package/src/{mdx-entries.ts → entries/mdx-entries.ts} +5 -5
  121. package/src/entries/run-directories.ts +108 -0
  122. package/src/entries/sources.ts +266 -0
  123. package/src/entries/static-module.ts +858 -0
  124. package/src/entries/test-runners.ts +868 -0
  125. package/src/{workflow-steps.ts → entries/workflow-steps.ts} +29 -11
  126. package/src/exempt.ts +3 -2
  127. package/src/extensions.ts +45 -0
  128. package/src/facts.ts +46 -0
  129. package/src/file-facts.ts +1 -1
  130. package/src/findings/boundary.ts +2 -0
  131. package/src/findings/completion.ts +43 -4
  132. package/src/findings/emitter.ts +1 -1
  133. package/src/findings/emitters.ts +14 -10
  134. package/src/{implementations.ts → findings/implementations.ts} +4 -4
  135. package/src/{in-operands.ts → findings/in-operands.ts} +3 -3
  136. package/src/findings/self-check.ts +41 -22
  137. package/src/findings/visibility-narrowing.ts +1 -1
  138. package/src/findings-pass.ts +5 -12
  139. package/src/framework-lifecycle.ts +43 -15
  140. package/src/fs/manifest.ts +25 -21
  141. package/src/generated-file.ts +240 -36
  142. package/src/graph.ts +27 -11
  143. package/src/import-bindings.ts +98 -29
  144. package/src/index/sites.ts +781 -0
  145. package/src/index.ts +1 -1
  146. package/src/indexed-access.ts +570 -527
  147. package/src/injection-container.ts +1 -1
  148. package/src/interface-satisfaction.ts +1 -1
  149. package/src/inventory/commonjs.ts +102 -17
  150. package/src/inventory/enumerate.ts +2 -1
  151. package/src/javascript-file.ts +29 -12
  152. package/src/keyof-comparisons.ts +131 -116
  153. package/src/load/classify.ts +49 -13
  154. package/src/load/diagnostics.ts +11 -1
  155. package/src/load/discover.ts +27 -11
  156. package/src/load/expected-module.ts +8 -2
  157. package/src/load/plan.ts +11 -2
  158. package/src/load/specifiers.ts +8 -5
  159. package/src/load/synthesize.ts +12 -6
  160. package/src/load/test-globals.ts +1 -1
  161. package/src/load/workspace-manifests.ts +1 -1
  162. package/src/load/workspace-resolution.ts +9 -2
  163. package/src/load/workspace-run.ts +1 -1
  164. package/src/matrix.ts +13 -17
  165. package/src/module-declarations.ts +74 -98
  166. package/src/overrides.ts +162 -134
  167. package/src/paths.ts +65 -1
  168. package/src/platform-calls.ts +119 -0
  169. package/src/platform-symbols.ts +189 -0
  170. package/src/references/read-rule.ts +60 -0
  171. package/src/references/read-rules.ts +55 -0
  172. package/src/references/sink.ts +213 -0
  173. package/src/references/sources.ts +632 -0
  174. package/src/references.ts +174 -1492
  175. package/src/report.ts +2 -2
  176. package/src/resolve.ts +1 -1
  177. package/src/{configured-declarations.ts → roots/configured-declarations.ts} +10 -7
  178. package/src/{entry-point-gaps.ts → roots/entry-point-gaps.ts} +5 -8
  179. package/src/{manifest.ts → roots/manifest.ts} +5 -5
  180. package/src/roots/published-reach.ts +481 -0
  181. package/src/{roots.ts → roots/root-set.ts} +203 -630
  182. package/src/roots/unseen-loads.ts +345 -0
  183. package/src/serialization-contract.ts +9 -4
  184. package/src/source-files.ts +5 -10
  185. package/src/stores.ts +13 -2
  186. package/src/suppress.ts +48 -33
  187. package/src/sweep.ts +37 -14
  188. package/src/symbol-keys.ts +102 -102
  189. package/src/tests/file-class.ts +118 -0
  190. package/src/{outside-tests.ts → tests/outside.ts} +16 -10
  191. package/src/{test-support.ts → tests/support.ts} +15 -21
  192. package/src/type-parameter-reads.ts +187 -158
  193. package/src/unimplemented-callees.ts +297 -280
  194. package/src/verbs/analyze.ts +19 -5
  195. package/src/verbs/describe.ts +5 -2
  196. package/src/verbs/explain.ts +75 -32
  197. package/src/verbs/print-retained.ts +2 -2
  198. package/dist/src/build-scripts.js +0 -418
  199. package/dist/src/conventions.js +0 -907
  200. package/dist/src/entry-points.js +0 -444
  201. package/dist/src/own-body.js +0 -28
  202. package/dist/src/roots.js +0 -865
  203. package/dist/src/unseen-loads.js +0 -189
  204. package/src/build-scripts.ts +0 -536
  205. package/src/entry-points.ts +0 -584
  206. package/src/own-body.ts +0 -42
  207. package/src/unseen-loads.ts +0 -282
@@ -0,0 +1,557 @@
1
+ /**
2
+ * The one syntax walk of a file every reference source and read rule shares: it finds the
3
+ * name nodes that are uses, the stores, the re-exports, the evaluated modules, the module
4
+ * URLs, the workers, the load calls, the decorators, the parameter properties and the keyed
5
+ * accesses, and offers every node to the read rules with its enclosing declaration.
6
+ */
7
+ import { isArrayLiteralExpression, isAsExpression, isBinaryExpression, isCallExpression, isDecorator, isDeleteExpression, isElementAccessExpression, isExportDeclaration, isExpressionStatement, isExternalModuleReference, isForInStatement, isForOfStatement, isForStatement, isIdentifier, isImportDeclaration, isImportEqualsDeclaration, isMetaProperty, isNamespaceExport, isNewExpression, isNoSubstitutionTemplateLiteral, isObjectLiteralExpression, isParenthesizedExpression, isPostfixUnaryExpression, isPrefixUnaryExpression, isPropertyAccessExpression, isPropertyAssignment, isShorthandPropertyAssignment, isSpreadAssignment, isSpreadElement, isStringLiteral, isVoidExpression, SyntaxKind, } from "@typescript/native/ast";
8
+ import { amdLoadOf } from "../amd.js";
9
+ import { writtenValue } from "../entries/static-module.js";
10
+ import { propertyReadsOf } from "../destructuring.js";
11
+ import { isParameterProperty, nodeKey } from "../inventory.js";
12
+ import { namespaceUses } from "../namespace-objects.js";
13
+ import { startsRelativePath } from "../paths.js";
14
+ import { writtenName } from "../platform-calls.js";
15
+ import { isLoadCall } from "../roots/unseen-loads.js";
16
+ import { keyNameOf } from "../symbol-keys.js";
17
+ import { parenthesesRemoved } from "../unwrap.js";
18
+ import { handedOn, valuesOf } from "../value-flow.js";
19
+ /**
20
+ * The operators whose left side one assignment stores into. A compound assignment is
21
+ * among them: where its value is discarded it reads its target only to write the result
22
+ * back, so nothing else receives what it read.
23
+ */
24
+ const ASSIGNMENTS = new Set([
25
+ SyntaxKind.EqualsToken,
26
+ SyntaxKind.PlusEqualsToken,
27
+ SyntaxKind.MinusEqualsToken,
28
+ SyntaxKind.AsteriskEqualsToken,
29
+ SyntaxKind.AsteriskAsteriskEqualsToken,
30
+ SyntaxKind.SlashEqualsToken,
31
+ SyntaxKind.PercentEqualsToken,
32
+ SyntaxKind.LessThanLessThanEqualsToken,
33
+ SyntaxKind.GreaterThanGreaterThanEqualsToken,
34
+ SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken,
35
+ SyntaxKind.AmpersandEqualsToken,
36
+ SyntaxKind.BarEqualsToken,
37
+ SyntaxKind.BarBarEqualsToken,
38
+ SyntaxKind.AmpersandAmpersandEqualsToken,
39
+ SyntaxKind.QuestionQuestionEqualsToken,
40
+ SyntaxKind.CaretEqualsToken,
41
+ ]);
42
+ /**
43
+ * The assignments that read their target to decide whether to store at all, so the read
44
+ * carries information out whatever becomes of the result.
45
+ */
46
+ const LOGICAL_ASSIGNMENTS = new Set([
47
+ SyntaxKind.BarBarEqualsToken,
48
+ SyntaxKind.AmpersandAmpersandEqualsToken,
49
+ SyntaxKind.QuestionQuestionEqualsToken,
50
+ ]);
51
+ /**
52
+ * Whether the value of one store expression is discarded: it is a statement of its own, a
53
+ * clause of a `for` loop, the operand of `void`, or the left operand of a comma.
54
+ */
55
+ function valueDiscarded(node) {
56
+ let child = node;
57
+ let parent = node.parent;
58
+ while (isParenthesizedExpression(parent)) {
59
+ child = parent;
60
+ parent = parent.parent;
61
+ }
62
+ if (isExpressionStatement(parent) || isVoidExpression(parent)) {
63
+ return true;
64
+ }
65
+ if (isForStatement(parent)) {
66
+ return parent.initializer === child || parent.incrementor === child;
67
+ }
68
+ return (isBinaryExpression(parent) &&
69
+ parent.operatorToken.kind === SyntaxKind.CommaToken &&
70
+ parent.left === child);
71
+ }
72
+ /** Whether one node is an identifier or a private name, the two forms a name takes. */
73
+ function isName(node) {
74
+ return node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.PrivateIdentifier;
75
+ }
76
+ /**
77
+ * Records the name one store writes into.
78
+ *
79
+ * A property access writes the member it names. An element access writes the collection
80
+ * it stores into, since a collection a module only stores into holds nothing anything
81
+ * reads, and joins `accesses` for the member a unique-symbol key selects. A destructuring
82
+ * target writes each name it binds, through its spreads and nested patterns.
83
+ */
84
+ function markWrite(target, writes, accesses) {
85
+ const held = parenthesesRemoved(target);
86
+ if (isName(held)) {
87
+ writes.add(held.pos);
88
+ return;
89
+ }
90
+ if (isPropertyAccessExpression(held)) {
91
+ if (isName(held.name)) {
92
+ writes.add(held.name.pos);
93
+ }
94
+ return;
95
+ }
96
+ if (isElementAccessExpression(held)) {
97
+ accesses.add(held);
98
+ // A store through a member's value lands in storage every holder of the value
99
+ // reads, so it reads the member; a variable only ever stored into stays written.
100
+ if (!isPropertyAccessExpression(parenthesesRemoved(held.expression))) {
101
+ markWrite(held.expression, writes, accesses);
102
+ }
103
+ return;
104
+ }
105
+ if (isArrayLiteralExpression(held)) {
106
+ for (const element of held.elements) {
107
+ markWrite(element, writes, accesses);
108
+ }
109
+ return;
110
+ }
111
+ if (isObjectLiteralExpression(held)) {
112
+ for (const property of held.properties) {
113
+ if (isPropertyAssignment(property)) {
114
+ markWrite(property.initializer, writes, accesses);
115
+ continue;
116
+ }
117
+ if (isShorthandPropertyAssignment(property)) {
118
+ markWrite(property.name, writes, accesses);
119
+ continue;
120
+ }
121
+ if (isSpreadAssignment(property)) {
122
+ markWrite(property.expression, writes, accesses);
123
+ }
124
+ }
125
+ return;
126
+ }
127
+ if (isSpreadElement(held)) {
128
+ markWrite(held.expression, writes, accesses);
129
+ }
130
+ }
131
+ /**
132
+ * Records every store one node performs: an assignment, a compound assignment, an
133
+ * increment or a decrement, a `delete`, and an iteration that assigns to a name declared
134
+ * elsewhere. An iteration that declares its own name stores into nothing the inventory
135
+ * holds. A store that reads its target as well records it in `reads`: a logical
136
+ * assignment, and a compound assignment, an increment or a decrement whose value is used.
137
+ */
138
+ function markStores(node, writes, reads, accesses) {
139
+ if (isBinaryExpression(node)) {
140
+ const operator = node.operatorToken.kind;
141
+ if (ASSIGNMENTS.has(operator)) {
142
+ markWrite(node.left, writes, accesses.written);
143
+ if (LOGICAL_ASSIGNMENTS.has(operator) ||
144
+ (operator !== SyntaxKind.EqualsToken && !valueDiscarded(node))) {
145
+ markWrite(node.left, reads, accesses.read);
146
+ }
147
+ }
148
+ return;
149
+ }
150
+ if (isPrefixUnaryExpression(node) || isPostfixUnaryExpression(node)) {
151
+ if (node.operator === SyntaxKind.PlusPlusToken ||
152
+ node.operator === SyntaxKind.MinusMinusToken) {
153
+ markWrite(node.operand, writes, accesses.written);
154
+ if (!valueDiscarded(node)) {
155
+ markWrite(node.operand, reads, accesses.read);
156
+ }
157
+ }
158
+ return;
159
+ }
160
+ if (isDeleteExpression(node)) {
161
+ markWrite(node.expression, writes, accesses.written);
162
+ return;
163
+ }
164
+ if (isForInStatement(node) || isForOfStatement(node)) {
165
+ if (node.initializer.kind !== SyntaxKind.VariableDeclarationList) {
166
+ markWrite(node.initializer, writes, accesses.written);
167
+ }
168
+ }
169
+ }
170
+ /** Whether one node is `import.meta.url`. */
171
+ function isImportMetaURL(node) {
172
+ const at = parenthesesRemoved(node);
173
+ return (isPropertyAccessExpression(at) &&
174
+ isMetaProperty(at.expression) &&
175
+ at.expression.keywordToken === SyntaxKind.ImportKeyword &&
176
+ at.name.text === "url");
177
+ }
178
+ /** The module URL one node builds, where it builds one. */
179
+ function moduleURLOf(node) {
180
+ const literal = (argument) => {
181
+ const at = argument === undefined ? undefined : parenthesesRemoved(argument);
182
+ return isLiteralText(at) ? at.text : undefined;
183
+ };
184
+ const constructor = isNewExpression(node) ? writtenName(node.expression) : undefined;
185
+ if (isNewExpression(node) && constructor !== undefined) {
186
+ const [reference, base] = node.arguments ?? [];
187
+ const specifier = literal(reference);
188
+ return specifier !== undefined && base !== undefined && isImportMetaURL(base)
189
+ ? { specifier, constructor, at: node }
190
+ : undefined;
191
+ }
192
+ if (isCallExpression(node)) {
193
+ const callee = parenthesesRemoved(node.expression);
194
+ const specifier = literal(node.arguments[0]);
195
+ if (specifier !== undefined &&
196
+ startsRelativePath(specifier) &&
197
+ isPropertyAccessExpression(callee) &&
198
+ isMetaProperty(callee.expression) &&
199
+ callee.expression.keywordToken === SyntaxKind.ImportKeyword &&
200
+ callee.name.text === "resolve") {
201
+ return { specifier, constructor: undefined, at: node };
202
+ }
203
+ }
204
+ return undefined;
205
+ }
206
+ /** The constructors whose first argument addresses a worker. */
207
+ export const WORKER_CONSTRUCTORS = new Set(["Worker", "SharedWorker"]);
208
+ /** Whether an options argument is an object literal whose `eval` member is written as anything but `false`. */
209
+ function evaluatesCode(options) {
210
+ const at = options === undefined ? undefined : parenthesesRemoved(options);
211
+ return (at !== undefined &&
212
+ isObjectLiteralExpression(at) &&
213
+ at.properties.some((property) => (isShorthandPropertyAssignment(property) &&
214
+ isIdentifier(property.name) &&
215
+ property.name.text === "eval") ||
216
+ (isPropertyAssignment(property) &&
217
+ (isIdentifier(property.name) || isStringLiteral(property.name)) &&
218
+ property.name.text === "eval" &&
219
+ parenthesesRemoved(property.initializer).kind !== SyntaxKind.FalseKeyword)));
220
+ }
221
+ /** The worker one node starts by a literal address or a path of its own directory, where it starts one. */
222
+ function workerOf(node) {
223
+ if (isNewExpression(node)) {
224
+ const constructor = writtenName(node.expression);
225
+ const [address, options] = node.arguments ?? [];
226
+ const literal = address === undefined ? undefined : parenthesesRemoved(address);
227
+ const value = literal === undefined ? undefined : writtenValue(literal);
228
+ const ownDirectory = value?.kind === "directory";
229
+ const text = value?.kind === "directory"
230
+ ? value.segments.join("/")
231
+ : isLiteralText(literal)
232
+ ? literal.text
233
+ : undefined;
234
+ // A thread's constructor may be imported under another name, whose path is relative.
235
+ if (constructor === undefined ||
236
+ text === undefined ||
237
+ (!WORKER_CONSTRUCTORS.has(constructor.text) && !ownDirectory && !startsRelativePath(text))) {
238
+ return undefined;
239
+ }
240
+ const callee = parenthesesRemoved(node.expression);
241
+ const holder = isPropertyAccessExpression(callee)
242
+ ? parenthesesRemoved(callee.expression)
243
+ : undefined;
244
+ return {
245
+ address: text,
246
+ ownDirectory,
247
+ constructor,
248
+ holder: holder !== undefined && isIdentifier(holder) ? holder : undefined,
249
+ evaluated: evaluatesCode(options),
250
+ at: node,
251
+ };
252
+ }
253
+ if (!isCallExpression(node)) {
254
+ return undefined;
255
+ }
256
+ const callee = parenthesesRemoved(node.expression);
257
+ const registry = isPropertyAccessExpression(callee) && callee.name.text === "register"
258
+ ? parenthesesRemoved(callee.expression)
259
+ : undefined;
260
+ const navigator = registry !== undefined &&
261
+ isPropertyAccessExpression(registry) &&
262
+ registry.name.text === "serviceWorker"
263
+ ? writtenName(registry.expression)
264
+ : undefined;
265
+ const [address] = node.arguments;
266
+ const literal = address === undefined ? undefined : parenthesesRemoved(address);
267
+ return navigator?.text === "navigator" && isLiteralText(literal)
268
+ ? {
269
+ address: literal.text,
270
+ ownDirectory: false,
271
+ constructor: navigator,
272
+ holder: undefined,
273
+ evaluated: false,
274
+ at: node,
275
+ }
276
+ : undefined;
277
+ }
278
+ /** Whether one node is a string literal or a template literal with no substitution. */
279
+ export function isLiteralText(node) {
280
+ return node !== undefined && (isStringLiteral(node) || isNoSubstitutionTemplateLiteral(node));
281
+ }
282
+ /**
283
+ * The module specifier of the module one node evaluates, if it evaluates one: an import
284
+ * declaration, an import-equals declaration of an external module, an export
285
+ * declaration that names a module, an `import()` call whose argument is literal text, and
286
+ * a call that may be a `require()` of literal text: one written as the name `require`, or
287
+ * one of a relative specifier through another name. A type-only form evaluates nothing.
288
+ * An `import()` of a computed argument names no module this pass can know.
289
+ */
290
+ function evaluationOf(node) {
291
+ if (isCallExpression(node) && node.expression.kind !== SyntaxKind.ImportKeyword) {
292
+ const [argument] = node.arguments;
293
+ const require = writtenName(node.expression);
294
+ if (require === undefined ||
295
+ !isLiteralText(argument) ||
296
+ (require.text !== "require" && !startsRelativePath(argument.text))) {
297
+ return undefined;
298
+ }
299
+ return { node: argument, require, whole: !discarded(node) };
300
+ }
301
+ const specifier = evaluatedBy(node);
302
+ return specifier === undefined ? undefined : { node: specifier };
303
+ }
304
+ /** Whether an expression's value is thrown away: it is a statement of its own, or `void`'s operand. */
305
+ function discarded(expression) {
306
+ let at = expression.parent;
307
+ while (isParenthesizedExpression(at)) {
308
+ at = at.parent;
309
+ }
310
+ return isExpressionStatement(at) || isVoidExpression(at);
311
+ }
312
+ function evaluatedBy(node) {
313
+ if (isImportDeclaration(node)) {
314
+ return node.importClause?.phaseModifier === SyntaxKind.TypeKeyword
315
+ ? undefined
316
+ : node.moduleSpecifier;
317
+ }
318
+ if (isExportDeclaration(node)) {
319
+ return node.isTypeOnly ? undefined : node.moduleSpecifier;
320
+ }
321
+ if (isImportEqualsDeclaration(node)) {
322
+ const reference = node.moduleReference;
323
+ return !node.isTypeOnly && isExternalModuleReference(reference)
324
+ ? reference.expression
325
+ : undefined;
326
+ }
327
+ if (isCallExpression(node) && node.expression.kind === SyntaxKind.ImportKeyword) {
328
+ const [argument] = node.arguments;
329
+ return isLiteralText(argument) ? argument : undefined;
330
+ }
331
+ return undefined;
332
+ }
333
+ /**
334
+ * The re-exports one node writes, if it is an export declaration. A specifier and a
335
+ * namespace export are declarations whose names are where they are written, so no use is
336
+ * read from them; each references what it carries forward instead. A bare star declares
337
+ * nothing, so the declaration enclosing it, at the top level the file, references the
338
+ * module it names.
339
+ */
340
+ function linksOf(file, node, declarations, enclosing) {
341
+ if (!isExportDeclaration(node)) {
342
+ return [];
343
+ }
344
+ const clause = node.exportClause;
345
+ const specifier = node.moduleSpecifier;
346
+ if (clause === undefined) {
347
+ return specifier === undefined
348
+ ? []
349
+ : [{ node: specifier, at: specifier, from: enclosing, alias: false }];
350
+ }
351
+ if (isNamespaceExport(clause)) {
352
+ const from = declarations.get(nodeKey(file, clause));
353
+ return from === undefined
354
+ ? []
355
+ : [{ node: clause.name, at: specifier ?? clause.name, from, alias: true }];
356
+ }
357
+ const found = [];
358
+ for (const element of clause.elements) {
359
+ const from = declarations.get(nodeKey(file, element));
360
+ if (from !== undefined) {
361
+ found.push({
362
+ node: element.name,
363
+ at: element.propertyName ?? element.name,
364
+ from,
365
+ alias: true,
366
+ });
367
+ }
368
+ }
369
+ return found;
370
+ }
371
+ /**
372
+ * Whether one object literal is a destructuring target, written on the left of an
373
+ * assignment or as a `for` loop's initializer, through the literals and spreads it nests in.
374
+ */
375
+ function isAssignmentPattern(node) {
376
+ let child = node;
377
+ let parent = node.parent;
378
+ while (isParenthesizedExpression(parent) ||
379
+ isArrayLiteralExpression(parent) ||
380
+ isObjectLiteralExpression(parent) ||
381
+ isSpreadElement(parent) ||
382
+ isSpreadAssignment(parent) ||
383
+ (isPropertyAssignment(parent) && parent.initializer === child)) {
384
+ child = parent;
385
+ parent = parent.parent;
386
+ }
387
+ if (isBinaryExpression(parent)) {
388
+ return parent.operatorToken.kind === SyntaxKind.EqualsToken && parent.left === child;
389
+ }
390
+ return (isForInStatement(parent) || isForOfStatement(parent)) && parent.initializer === child;
391
+ }
392
+ /**
393
+ * Every name node one file holds that is a use rather than a declaration, in source
394
+ * order, each with its enclosing declaration and its use, and every re-export the file
395
+ * writes. One walk answers all of it, because a second would have to agree with this one
396
+ * about which nodes are names. A declaration's own declared name is left out, which is
397
+ * what makes a declaration referenced only from its own site an unreferenced one, and so
398
+ * is every node of `unread`, a subtree that is no use.
399
+ */
400
+ export function sitesOf(file, declarations, fileId, unread, offer) {
401
+ const found = [];
402
+ const reads = [];
403
+ const links = [];
404
+ const evaluations = [];
405
+ const wholes = [];
406
+ const urls = [];
407
+ const workers = [];
408
+ const loadCalls = [];
409
+ const decorated = [];
410
+ const parameterWrites = [];
411
+ const namespaces = namespaceUses(file);
412
+ const literals = [];
413
+ const flows = [];
414
+ const writes = new Set();
415
+ const alsoRead = new Set();
416
+ const accesses = { written: new Set(), read: new Set() };
417
+ const keyed = [];
418
+ const declared = new Set();
419
+ const shorthands = new Map();
420
+ let enclosing = fileId;
421
+ const markNames = (node) => {
422
+ if (isShorthandPropertyAssignment(node)) {
423
+ shorthands.set(node.name.pos, node);
424
+ return;
425
+ }
426
+ // A property access carries the member it names where a declaration carries its
427
+ // declared name, and it is the one form of the grammar that does.
428
+ if (isPropertyAccessExpression(node)) {
429
+ return;
430
+ }
431
+ const named = node;
432
+ for (const name of [named.name, named.propertyName]) {
433
+ if (name !== undefined && isName(name)) {
434
+ declared.add(name.pos);
435
+ }
436
+ }
437
+ };
438
+ // A read rule sees every node, an unread subtree's too, each with its enclosing declaration.
439
+ const offerAll = (node) => {
440
+ offer(node, enclosing);
441
+ node.forEachChild(offerAll);
442
+ };
443
+ const visit = (node) => {
444
+ if (unread.has(node)) {
445
+ offerAll(node);
446
+ return;
447
+ }
448
+ offer(node, enclosing);
449
+ const namespace = namespaces.get(node);
450
+ if (namespace?.kind === "whole") {
451
+ wholes.push({ specifier: namespace.specifier, at: node, from: enclosing });
452
+ }
453
+ else if (namespace?.kind === "indexed") {
454
+ found.push({ node: namespace.literal, shorthand: undefined, from: enclosing, use: "read" });
455
+ }
456
+ if (isName(node)) {
457
+ if (!declared.has(node.pos)) {
458
+ const site = { node, shorthand: shorthands.get(node.pos), from: enclosing };
459
+ if (writes.has(node.pos)) {
460
+ found.push({ ...site, use: "write" });
461
+ }
462
+ if (!writes.has(node.pos) || alsoRead.has(node.pos)) {
463
+ found.push({ ...site, use: "read" });
464
+ }
465
+ }
466
+ return;
467
+ }
468
+ markNames(node);
469
+ markStores(node, writes, alsoRead, accesses);
470
+ const key = isElementAccessExpression(node) ? keyNameOf(node.argumentExpression) : undefined;
471
+ if (key !== undefined && isElementAccessExpression(node)) {
472
+ const written = accesses.written.has(node);
473
+ keyed.push({
474
+ access: node,
475
+ key,
476
+ from: enclosing,
477
+ use: written ? (accesses.read.has(node) ? "both" : "write") : "read",
478
+ });
479
+ }
480
+ if (isObjectLiteralExpression(node) && !isAssignmentPattern(node)) {
481
+ literals.push({ literal: node, from: enclosing });
482
+ }
483
+ // An assertion needs only comparability, so no member of its operand is read by it.
484
+ for (const written of isAsExpression(node) ? [] : handedOn(node)) {
485
+ flows.push(...valuesOf(written).map((value) => ({ value, from: enclosing })));
486
+ }
487
+ for (const read of propertyReadsOf(node)) {
488
+ reads.push({ ...read, from: enclosing });
489
+ }
490
+ links.push(...linksOf(file, node, declarations, enclosing));
491
+ const evaluated = evaluationOf(node);
492
+ if (evaluated !== undefined) {
493
+ evaluations.push({ ...evaluated, from: enclosing });
494
+ }
495
+ const amd = amdLoadOf(node);
496
+ if (amd !== undefined) {
497
+ const { callee, ids } = amd;
498
+ for (const { id, received } of ids) {
499
+ evaluations.push({
500
+ node: id,
501
+ require: callee,
502
+ whole: received,
503
+ amd: true,
504
+ from: enclosing,
505
+ });
506
+ }
507
+ }
508
+ const url = moduleURLOf(node);
509
+ if (url !== undefined) {
510
+ urls.push({ ...url, from: enclosing });
511
+ }
512
+ const worker = workerOf(node);
513
+ if (worker !== undefined) {
514
+ workers.push({ ...worker, from: enclosing });
515
+ }
516
+ if (isLoadCall(node)) {
517
+ loadCalls.push({ call: node, from: enclosing });
518
+ }
519
+ const held = declarations.get(nodeKey(file, node));
520
+ const outer = enclosing;
521
+ // A parameter property's annotation, initializer and decorators stay with the
522
+ // parameter when the member goes, so they are written inside the constructor's class.
523
+ if (held !== undefined && isParameterProperty(node)) {
524
+ parameterWrites.push({
525
+ name: node.name,
526
+ from: outer,
527
+ member: held,
528
+ });
529
+ }
530
+ else if (held !== undefined) {
531
+ enclosing = held;
532
+ for (const modifier of node.modifiers ?? []) {
533
+ if (isDecorator(modifier)) {
534
+ decorated.push({ decorator: modifier, declaration: held });
535
+ }
536
+ }
537
+ }
538
+ node.forEachChild(visit);
539
+ enclosing = outer;
540
+ };
541
+ file.forEachChild(visit);
542
+ return {
543
+ uses: found,
544
+ literals,
545
+ flows,
546
+ reads,
547
+ links,
548
+ evaluations,
549
+ wholes,
550
+ urls,
551
+ workers,
552
+ loadCalls,
553
+ decorated,
554
+ parameterWrites,
555
+ keyed,
556
+ };
557
+ }
package/dist/src/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export { run, SETTING_OPTIONS } from "./run.js";
2
- export { DECLINED_CONVENTIONS } from "./entry-point-gaps.js";
2
+ export { DECLINED_CONVENTIONS } from "./roots/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
5
  export { CONTRACT_VERSION } from "./contract/contract.generated.js";