@lucasacoutinho/archer 0.2.1 → 0.3.0

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 (214) hide show
  1. package/README.md +144 -387
  2. package/dist/analyzer/Analyzer.d.ts +17 -0
  3. package/dist/analyzer/Analyzer.d.ts.map +1 -0
  4. package/dist/analyzer/Analyzer.js +15 -0
  5. package/dist/analyzer/Analyzer.js.map +1 -0
  6. package/dist/analyzer/bindings.d.ts +26 -0
  7. package/dist/analyzer/bindings.d.ts.map +1 -0
  8. package/dist/analyzer/bindings.js +61 -0
  9. package/dist/analyzer/bindings.js.map +1 -0
  10. package/dist/analyzer/errors.d.ts +34 -0
  11. package/dist/analyzer/errors.d.ts.map +1 -0
  12. package/dist/analyzer/errors.js +20 -0
  13. package/dist/analyzer/errors.js.map +1 -0
  14. package/dist/analyzer/graph-file.d.ts +13 -0
  15. package/dist/analyzer/graph-file.d.ts.map +1 -0
  16. package/dist/analyzer/graph-file.js +22 -0
  17. package/dist/analyzer/graph-file.js.map +1 -0
  18. package/dist/analyzer/paths.d.ts +12 -0
  19. package/dist/analyzer/paths.d.ts.map +1 -0
  20. package/dist/analyzer/paths.js +26 -0
  21. package/dist/analyzer/paths.js.map +1 -0
  22. package/dist/analyzer/server-exit.d.ts +19 -0
  23. package/dist/analyzer/server-exit.d.ts.map +1 -0
  24. package/dist/analyzer/server-exit.js +70 -0
  25. package/dist/analyzer/server-exit.js.map +1 -0
  26. package/dist/analyzer/source.d.ts +29 -0
  27. package/dist/analyzer/source.d.ts.map +1 -0
  28. package/dist/analyzer/source.js +58 -0
  29. package/dist/analyzer/source.js.map +1 -0
  30. package/dist/analyzer/syntax.d.ts +29 -0
  31. package/dist/analyzer/syntax.d.ts.map +1 -0
  32. package/dist/analyzer/syntax.js +226 -0
  33. package/dist/analyzer/syntax.js.map +1 -0
  34. package/dist/analyzer/targets.d.ts +26 -0
  35. package/dist/analyzer/targets.d.ts.map +1 -0
  36. package/dist/analyzer/targets.js +84 -0
  37. package/dist/analyzer/targets.js.map +1 -0
  38. package/dist/analyzer/typescript.d.ts +5 -0
  39. package/dist/analyzer/typescript.d.ts.map +1 -0
  40. package/dist/analyzer/typescript.js +221 -0
  41. package/dist/analyzer/typescript.js.map +1 -0
  42. package/dist/analyzer/workspace.d.ts +24 -0
  43. package/dist/analyzer/workspace.d.ts.map +1 -0
  44. package/dist/analyzer/workspace.js +9 -0
  45. package/dist/analyzer/workspace.js.map +1 -0
  46. package/dist/cli/explain.d.ts +3 -0
  47. package/dist/cli/explain.d.ts.map +1 -0
  48. package/dist/cli/explain.js +21 -0
  49. package/dist/cli/explain.js.map +1 -0
  50. package/dist/cli/main.d.ts +3 -0
  51. package/dist/cli/main.d.ts.map +1 -0
  52. package/dist/cli/main.js +159 -0
  53. package/dist/cli/main.js.map +1 -0
  54. package/dist/config/input.d.ts +59 -0
  55. package/dist/config/input.d.ts.map +1 -0
  56. package/dist/config/input.js +115 -0
  57. package/dist/config/input.js.map +1 -0
  58. package/dist/config/rules.d.ts +94 -0
  59. package/dist/config/rules.d.ts.map +1 -0
  60. package/dist/config/rules.js +130 -0
  61. package/dist/config/rules.js.map +1 -0
  62. package/dist/core/baseline.d.ts +16 -0
  63. package/dist/core/baseline.d.ts.map +1 -0
  64. package/dist/core/baseline.js +25 -0
  65. package/dist/core/baseline.js.map +1 -0
  66. package/dist/core/check.d.ts +16 -0
  67. package/dist/core/check.d.ts.map +1 -0
  68. package/dist/core/check.js +271 -0
  69. package/dist/core/check.js.map +1 -0
  70. package/dist/core/config.d.ts +72 -0
  71. package/dist/core/config.d.ts.map +1 -0
  72. package/dist/core/config.js +78 -0
  73. package/dist/core/config.js.map +1 -0
  74. package/dist/core/fingerprint.d.ts +54 -0
  75. package/dist/core/fingerprint.d.ts.map +1 -0
  76. package/dist/core/fingerprint.js +182 -0
  77. package/dist/core/fingerprint.js.map +1 -0
  78. package/dist/core/keys.d.ts +10 -0
  79. package/dist/core/keys.d.ts.map +1 -0
  80. package/dist/core/keys.js +16 -0
  81. package/dist/core/keys.js.map +1 -0
  82. package/dist/core/lower.d.ts +13 -0
  83. package/dist/core/lower.d.ts.map +1 -0
  84. package/dist/core/lower.js +82 -0
  85. package/dist/core/lower.js.map +1 -0
  86. package/dist/core/model.d.ts +155 -0
  87. package/dist/core/model.d.ts.map +1 -0
  88. package/dist/core/model.js +116 -0
  89. package/dist/core/model.js.map +1 -0
  90. package/dist/core/pattern.d.ts +13 -0
  91. package/dist/core/pattern.d.ts.map +1 -0
  92. package/dist/core/pattern.js +29 -0
  93. package/dist/core/pattern.js.map +1 -0
  94. package/dist/core/reach.d.ts +10 -0
  95. package/dist/core/reach.d.ts.map +1 -0
  96. package/dist/core/reach.js +81 -0
  97. package/dist/core/reach.js.map +1 -0
  98. package/dist/core/rule.d.ts +200 -0
  99. package/dist/core/rule.d.ts.map +1 -0
  100. package/dist/core/rule.js +162 -0
  101. package/dist/core/rule.js.map +1 -0
  102. package/dist/core/selector.d.ts +7 -0
  103. package/dist/core/selector.d.ts.map +1 -0
  104. package/dist/core/selector.js +27 -0
  105. package/dist/core/selector.js.map +1 -0
  106. package/dist/core/structural.d.ts +10 -0
  107. package/dist/core/structural.d.ts.map +1 -0
  108. package/dist/core/structural.js +24 -0
  109. package/dist/core/structural.js.map +1 -0
  110. package/dist/core/text.d.ts +26 -0
  111. package/dist/core/text.d.ts.map +1 -0
  112. package/dist/core/text.js +144 -0
  113. package/dist/core/text.js.map +1 -0
  114. package/dist/effect.d.ts +19 -0
  115. package/dist/effect.d.ts.map +1 -0
  116. package/dist/effect.js +21 -0
  117. package/dist/effect.js.map +1 -0
  118. package/dist/index.d.ts +24 -44
  119. package/dist/index.d.ts.map +1 -0
  120. package/dist/index.js +59 -52
  121. package/dist/index.js.map +1 -0
  122. package/dist/report/agent.d.ts +3 -0
  123. package/dist/report/agent.d.ts.map +1 -0
  124. package/dist/report/agent.js +35 -0
  125. package/dist/report/agent.js.map +1 -0
  126. package/dist/report/dot.d.ts +4 -0
  127. package/dist/report/dot.d.ts.map +1 -0
  128. package/dist/report/dot.js +15 -0
  129. package/dist/report/dot.js.map +1 -0
  130. package/dist/report/github.d.ts +3 -0
  131. package/dist/report/github.d.ts.map +1 -0
  132. package/dist/report/github.js +18 -0
  133. package/dist/report/github.js.map +1 -0
  134. package/dist/report/json.d.ts +3 -0
  135. package/dist/report/json.d.ts.map +1 -0
  136. package/dist/report/json.js +4 -0
  137. package/dist/report/json.js.map +1 -0
  138. package/dist/report/message.d.ts +20 -0
  139. package/dist/report/message.d.ts.map +1 -0
  140. package/dist/report/message.js +73 -0
  141. package/dist/report/message.js.map +1 -0
  142. package/dist/report/pretty.d.ts +8 -0
  143. package/dist/report/pretty.d.ts.map +1 -0
  144. package/dist/report/pretty.js +89 -0
  145. package/dist/report/pretty.js.map +1 -0
  146. package/dist/report/render.d.ts +9 -0
  147. package/dist/report/render.d.ts.map +1 -0
  148. package/dist/report/render.js +10 -0
  149. package/dist/report/render.js.map +1 -0
  150. package/dist/report/report.d.ts +44 -0
  151. package/dist/report/report.d.ts.map +1 -0
  152. package/dist/report/report.js +49 -0
  153. package/dist/report/report.js.map +1 -0
  154. package/dist/report/sarif.d.ts +3 -0
  155. package/dist/report/sarif.d.ts.map +1 -0
  156. package/dist/report/sarif.js +68 -0
  157. package/dist/report/sarif.js.map +1 -0
  158. package/dist/run.d.ts +49 -0
  159. package/dist/run.d.ts.map +1 -0
  160. package/dist/run.js +87 -0
  161. package/dist/run.js.map +1 -0
  162. package/dist/shell/baseline-file.d.ts +20 -0
  163. package/dist/shell/baseline-file.d.ts.map +1 -0
  164. package/dist/shell/baseline-file.js +46 -0
  165. package/dist/shell/baseline-file.js.map +1 -0
  166. package/dist/shell/load-config.d.ts +19 -0
  167. package/dist/shell/load-config.d.ts.map +1 -0
  168. package/dist/shell/load-config.js +39 -0
  169. package/dist/shell/load-config.js.map +1 -0
  170. package/package.json +29 -177
  171. package/skills/archer/SKILL.md +127 -45
  172. package/skills/archer/agents/openai.yaml +2 -2
  173. package/skills/archer/references/rules.md +267 -54
  174. package/dist/bun/plugin.cjs +0 -85
  175. package/dist/bun/plugin.d.cts +0 -7
  176. package/dist/bun/plugin.d.ts +0 -7
  177. package/dist/bun/plugin.js +0 -11
  178. package/dist/bun.cjs +0 -2238
  179. package/dist/bun.d.cts +0 -13
  180. package/dist/bun.d.ts +0 -13
  181. package/dist/bun.js +0 -28
  182. package/dist/chunk-2AKMBLHG.js +0 -2165
  183. package/dist/chunk-67YEOTXP.js +0 -25
  184. package/dist/chunk-IDVLHNL2.js +0 -46
  185. package/dist/chunk-ZZ6TR4PO.js +0 -201
  186. package/dist/cli.js +0 -2643
  187. package/dist/index.cjs +0 -2484
  188. package/dist/index.d.cts +0 -45
  189. package/dist/jest/plugin.cjs +0 -85
  190. package/dist/jest/plugin.d.cts +0 -7
  191. package/dist/jest/plugin.d.ts +0 -7
  192. package/dist/jest/plugin.js +0 -11
  193. package/dist/jest.cjs +0 -2237
  194. package/dist/jest.d.cts +0 -13
  195. package/dist/jest.d.ts +0 -13
  196. package/dist/jest.js +0 -27
  197. package/dist/matchers-Cqnbsyxe.d.cts +0 -11
  198. package/dist/matchers-Cqnbsyxe.d.ts +0 -11
  199. package/dist/node.cjs +0 -2237
  200. package/dist/node.d.cts +0 -13
  201. package/dist/node.d.ts +0 -13
  202. package/dist/node.js +0 -27
  203. package/dist/reporters-BbAXMpuW.d.cts +0 -6
  204. package/dist/reporters-xh-HQneS.d.ts +0 -6
  205. package/dist/suite-BwnPDCvU.d.cts +0 -337
  206. package/dist/suite-BwnPDCvU.d.ts +0 -337
  207. package/dist/vitest/plugin.cjs +0 -85
  208. package/dist/vitest/plugin.d.cts +0 -7
  209. package/dist/vitest/plugin.d.ts +0 -7
  210. package/dist/vitest/plugin.js +0 -11
  211. package/dist/vitest.cjs +0 -2531
  212. package/dist/vitest.d.cts +0 -37
  213. package/dist/vitest.d.ts +0 -37
  214. package/dist/vitest.js +0 -139
@@ -0,0 +1,226 @@
1
+ import { Match } from "effect";
2
+ import { isArrayBindingPattern, isBinaryExpression, isCallExpression, isClassDeclaration, isConstructorDeclaration, isDecorator, isElementAccessExpression, isEnumDeclaration, isExportAssignment, isExportDeclaration, isExternalModuleReference, isFunctionDeclaration, isIdentifier, isImportDeclaration, isImportEqualsDeclaration, isImportTypeNode, isInterfaceDeclaration, isLiteralTypeNode, isMethodDeclaration, isMethodSignatureDeclaration, isNamedExports, isObjectBindingPattern, isParameterDeclaration, isPrivateIdentifier, isPropertyAccessExpression, isPropertyDeclaration, isPropertySignatureDeclaration, isStringLiteralLikeNode, isTypeAliasDeclaration, isVariableStatement, ModifierFlags, ScriptKind, SyntaxKind, } from "typescript/unstable/ast";
3
+ export const locationOf = (sourceFile, node) => {
4
+ const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
5
+ return { line: line + 1, column: character + 1 };
6
+ };
7
+ /** A trailing newline ends the last line instead of starting another; an empty file has no lines. */
8
+ export const countLines = (text) => {
9
+ if (text === "") {
10
+ return 0;
11
+ }
12
+ let lines = text.endsWith("\n") ? 0 : 1;
13
+ for (let at = text.indexOf("\n"); at >= 0; at = text.indexOf("\n", at + 1)) {
14
+ lines++;
15
+ }
16
+ return lines;
17
+ };
18
+ const hasFlag = (node, flag) => (node.modifierFlags & flag) !== 0;
19
+ const memberOf = (object, member) => isIdentifier(object) && member !== undefined ? { _tag: "Member", root: object, member } : { _tag: "Other" };
20
+ const calleeOf = Match.type().pipe(Match.when(isIdentifier, (identifier) => ({ _tag: "Name", identifier })), Match.when(isPropertyAccessExpression, (access) => memberOf(access.expression, propertyName(access))), Match.when(isElementAccessExpression, (access) => memberOf(access.expression, isStringLiteralLikeNode(access.argumentExpression) ? access.argumentExpression.text : undefined)), Match.when((node) => node.kind === SyntaxKind.ImportKeyword, () => ({ _tag: "ImportKeyword" })), Match.orElse(() => ({ _tag: "Other" })));
21
+ const propertyName = (access) => isIdentifier(access.name) ? access.name.text : undefined;
22
+ /** An empty `import {} from` still runs the module, so it is not type-only. */
23
+ const importsOnlyTypes = (declaration) => {
24
+ const clause = declaration.importClause;
25
+ if (clause === undefined) {
26
+ return false;
27
+ }
28
+ if (clause.phaseModifier === SyntaxKind.TypeKeyword) {
29
+ return true;
30
+ }
31
+ const bindings = clause.namedBindings;
32
+ return (clause.name === undefined &&
33
+ bindings !== undefined &&
34
+ bindings.kind === SyntaxKind.NamedImports &&
35
+ bindings.elements.length > 0 &&
36
+ bindings.elements.every((element) => element.isTypeOnly));
37
+ };
38
+ const exportsOnlyTypes = (declaration) => {
39
+ const clause = declaration.exportClause;
40
+ return (declaration.isTypeOnly ||
41
+ (clause !== undefined &&
42
+ isNamedExports(clause) &&
43
+ clause.elements.length > 0 &&
44
+ clause.elements.every((element) => element.isTypeOnly)));
45
+ };
46
+ export const scanSource = (sourceFile) => {
47
+ const sites = [];
48
+ const calls = [];
49
+ const looseEqualities = [];
50
+ const scripted = sourceFile.scriptKind === ScriptKind.JS || sourceFile.scriptKind === ScriptKind.JSX;
51
+ const addLiteral = (kind, node, checkable) => {
52
+ if (node !== undefined && isStringLiteralLikeNode(node)) {
53
+ sites.push({ kind, node, specifier: node.text, computed: false, checkable });
54
+ }
55
+ };
56
+ const addArgument = (kind, argument, checkable) => {
57
+ if (isStringLiteralLikeNode(argument)) {
58
+ addLiteral(kind, argument, checkable);
59
+ }
60
+ else {
61
+ sites.push({ kind, node: argument, specifier: argument.getText(sourceFile), computed: true, checkable: false });
62
+ }
63
+ };
64
+ const addCall = (call) => {
65
+ const [first] = call.arguments;
66
+ Match.valueTags(calleeOf(call.expression), {
67
+ ImportKeyword: () => {
68
+ if (first !== undefined) {
69
+ addArgument("dynamic", first, true);
70
+ }
71
+ },
72
+ Name: ({ identifier }) => {
73
+ if (identifier.text === "require" && call.arguments.length === 1 && first !== undefined) {
74
+ addArgument("require", first, scripted);
75
+ }
76
+ calls.push({ name: identifier.text, root: identifier, member: undefined, callee: identifier });
77
+ },
78
+ Member: ({ root, member }) => {
79
+ calls.push({ name: `${root.text}.${member}`, root, member, callee: call.expression });
80
+ },
81
+ Other: () => undefined,
82
+ });
83
+ };
84
+ const read = Match.type().pipe(Match.when(isImportDeclaration, (node) => {
85
+ addLiteral(importsOnlyTypes(node) ? "type" : "static", node.moduleSpecifier, true);
86
+ return false;
87
+ }), Match.when(isExportDeclaration, (node) => {
88
+ addLiteral(exportsOnlyTypes(node) ? "type" : "static", node.moduleSpecifier, true);
89
+ return false;
90
+ }), Match.when(isImportEqualsDeclaration, (node) => {
91
+ if (isExternalModuleReference(node.moduleReference)) {
92
+ addLiteral(node.isTypeOnly ? "type" : "require", node.moduleReference.expression, true);
93
+ }
94
+ return false;
95
+ }), Match.when(isCallExpression, (node) => {
96
+ addCall(node);
97
+ return true;
98
+ }), Match.when(isImportTypeNode, (node) => {
99
+ addLiteral("type", isLiteralTypeNode(node.argument) ? node.argument.literal : undefined, true);
100
+ return true;
101
+ }), Match.when(isBinaryExpression, (node) => {
102
+ if (node.operatorToken.kind === SyntaxKind.EqualsEqualsToken || node.operatorToken.kind === SyntaxKind.ExclamationEqualsToken) {
103
+ looseEqualities.push(node.operatorToken);
104
+ }
105
+ return true;
106
+ }), Match.orElse(() => true));
107
+ const visit = (node) => {
108
+ if (read(node)) {
109
+ node.forEachChild(visit);
110
+ }
111
+ return undefined;
112
+ };
113
+ sourceFile.forEachChild(visit);
114
+ return { sites, calls, looseEqualities };
115
+ };
116
+ export const requiredModule = (node) => node !== undefined &&
117
+ isCallExpression(node) &&
118
+ isIdentifier(node.expression) &&
119
+ node.expression.text === "require" &&
120
+ node.arguments.length === 1 &&
121
+ node.arguments[0] !== undefined &&
122
+ isStringLiteralLikeNode(node.arguments[0])
123
+ ? node.arguments[0].text
124
+ : undefined;
125
+ const memberName = (name) => isIdentifier(name) || isPrivateIdentifier(name) || isStringLiteralLikeNode(name) ? name.text : name.getText();
126
+ const visibilityOf = (flags, name) => Match.value(flags).pipe(Match.when((value) => (value & ModifierFlags.Private) !== 0 || isPrivateIdentifier(name), () => "private"), Match.when((value) => (value & ModifierFlags.Protected) !== 0, () => "protected"), Match.orElse(() => "public"));
127
+ const methodOf = (member) => isMethodDeclaration(member) || isMethodSignatureDeclaration(member)
128
+ ? {
129
+ name: memberName(member.name),
130
+ visibility: visibilityOf(member.modifierFlags, member.name),
131
+ isStatic: hasFlag(member, ModifierFlags.Static),
132
+ }
133
+ : undefined;
134
+ /** Overload signatures collapse into one entry. */
135
+ const methodsOf = (members) => {
136
+ const seen = new Set();
137
+ const methods = [];
138
+ for (const member of members) {
139
+ const method = methodOf(member);
140
+ const key = method === undefined ? "" : `${method.visibility}|${method.isStatic}|${method.name}`;
141
+ if (method !== undefined && !seen.has(key)) {
142
+ seen.add(key);
143
+ methods.push(method);
144
+ }
145
+ }
146
+ return methods;
147
+ };
148
+ const parameterPropertyFlags = ModifierFlags.Public | ModifierFlags.Private | ModifierFlags.Protected | ModifierFlags.Readonly;
149
+ /** Constructor parameter properties count as properties. */
150
+ const hasOnlyReadonlyProperties = (members) => {
151
+ const properties = members.flatMap((member) => isPropertyDeclaration(member) || isPropertySignatureDeclaration(member)
152
+ ? [member]
153
+ : isConstructorDeclaration(member)
154
+ ? member.parameters.filter((parameter) => isParameterDeclaration(parameter) && (parameter.modifierFlags & parameterPropertyFlags) !== 0)
155
+ : []);
156
+ return properties.length > 0 && properties.every((property) => hasFlag(property, ModifierFlags.Readonly));
157
+ };
158
+ /** `Controller` for `@Controller` and `@Controller()`. */
159
+ const decoratorNames = (sourceFile, node) => (isClassDeclaration(node) ? (node.modifiers ?? []) : []).flatMap((modifier) => isDecorator(modifier)
160
+ ? [(isCallExpression(modifier.expression) ? modifier.expression.expression : modifier.expression).getText(sourceFile)]
161
+ : []);
162
+ const heritageNames = (sourceFile, node, token) => (node.heritageClauses ?? [])
163
+ .filter((clause) => clause.token === token)
164
+ .flatMap((clause) => clause.types.map((type) => type.expression.getText(sourceFile)));
165
+ const boundNames = (name) => Match.value(name).pipe(Match.when(isIdentifier, (identifier) => [identifier.text]), Match.when(isObjectBindingPattern, (pattern) => pattern.elements.flatMap((element) => (element.name === undefined ? [] : boundNames(element.name)))), Match.when(isArrayBindingPattern, (pattern) => pattern.elements.flatMap((element) => (element.kind === SyntaxKind.BindingElement && element.name !== undefined ? boundNames(element.name) : []))), Match.orElse(() => []));
166
+ /** Names exported by `export { a as b }` and `export default a` instead of by a modifier. */
167
+ const exportedLocalNames = (sourceFile) => {
168
+ const names = new Set();
169
+ for (const statement of sourceFile.statements) {
170
+ if (isExportDeclaration(statement) && statement.moduleSpecifier === undefined && statement.exportClause !== undefined && isNamedExports(statement.exportClause)) {
171
+ for (const element of statement.exportClause.elements) {
172
+ names.add((element.propertyName ?? element.name).text);
173
+ }
174
+ }
175
+ else if (isExportAssignment(statement) && isIdentifier(statement.expression)) {
176
+ names.add(statement.expression.text);
177
+ }
178
+ }
179
+ return names;
180
+ };
181
+ /** A variable statement gives one declaration per bound name, all at the statement's location. */
182
+ export const declarationsOf = (sourceFile) => {
183
+ const exportedNames = exportedLocalNames(sourceFile);
184
+ const base = (node, name) => ({
185
+ name,
186
+ exported: hasFlag(node, ModifierFlags.Export) || exportedNames.has(name),
187
+ abstract: hasFlag(node, ModifierFlags.Abstract),
188
+ location: locationOf(sourceFile, node),
189
+ });
190
+ const plain = { extended: [], implemented: [], decorators: [], methods: [], readonlyProperties: false };
191
+ const read = Match.type().pipe(Match.when(isClassDeclaration, (node) => [
192
+ {
193
+ ...base(node, node.name?.text ?? "default"),
194
+ kind: "class",
195
+ extended: heritageNames(sourceFile, node, SyntaxKind.ExtendsKeyword),
196
+ implemented: heritageNames(sourceFile, node, SyntaxKind.ImplementsKeyword),
197
+ decorators: decoratorNames(sourceFile, node),
198
+ methods: methodsOf(node.members),
199
+ readonlyProperties: hasOnlyReadonlyProperties(node.members),
200
+ },
201
+ ]), Match.when(isInterfaceDeclaration, (node) => [
202
+ {
203
+ ...base(node, node.name.text),
204
+ kind: "interface",
205
+ extended: heritageNames(sourceFile, node, SyntaxKind.ExtendsKeyword),
206
+ implemented: [],
207
+ decorators: [],
208
+ methods: methodsOf(node.members),
209
+ readonlyProperties: hasOnlyReadonlyProperties(node.members),
210
+ },
211
+ ]), Match.when(isEnumDeclaration, (node) => [{ ...base(node, node.name.text), kind: "enum", ...plain }]), Match.when(isFunctionDeclaration, (node) => [
212
+ { ...base(node, node.name?.text ?? "default"), kind: "function", ...plain },
213
+ ]), Match.when(isTypeAliasDeclaration, (node) => [{ ...base(node, node.name.text), kind: "type", ...plain }]), Match.when(isVariableStatement, (node) => node.declarationList.declarations
214
+ .flatMap((declaration) => boundNames(declaration.name))
215
+ .map((name) => ({ ...base(node, name), kind: "variable", ...plain }))), Match.orElse(() => []));
216
+ const functions = new Set();
217
+ return sourceFile.statements.flatMap(read).filter((declaration) => {
218
+ if (declaration.kind !== "function") {
219
+ return true;
220
+ }
221
+ const fresh = !functions.has(declaration.name);
222
+ functions.add(declaration.name);
223
+ return fresh;
224
+ });
225
+ };
226
+ //# sourceMappingURL=syntax.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"syntax.js","sourceRoot":"","sources":["../../src/analyzer/syntax.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { Target } from "../core/model.ts";
2
+ /**
3
+ * `node:fs` and `fs` give `Builtin(node, "fs")`, `bun:test` gives
4
+ * `Builtin(bun, "test")`. The prefix alone makes a built-in, as at runtime;
5
+ * a bare name must be in Node's own list, so `node:test` is one and `test` is not.
6
+ */
7
+ export declare const builtinTarget: (specifier: string) => Target | undefined;
8
+ export interface PackageName {
9
+ readonly name: string;
10
+ readonly subpath: ReadonlyArray<string>;
11
+ }
12
+ /** Scope-aware: `@scope/pkg/sub/path` is `@scope/pkg` with subpath `["sub", "path"]`. */
13
+ export declare const specifierPackage: (specifier: string) => PackageName | undefined;
14
+ /** The segment after the last `node_modules`, so nested and pnpm layouts both name the right package. */
15
+ export declare const installedPackage: (segments: ReadonlyArray<string>) => PackageName | undefined;
16
+ export declare const isInstalled: (segments: ReadonlyArray<string>) => boolean;
17
+ /**
18
+ * The specifier names the package when it is a package specifier for the
19
+ * package that was found: `picomatch` stays `picomatch` when the file is in
20
+ * `@types/picomatch`, and `react/jsx-runtime` keeps its subpath. Otherwise the
21
+ * file's own package decides, as for a path alias or a `#` import.
22
+ */
23
+ export declare const packageTarget: (specifier: string, installed: PackageName | undefined) => Target | undefined;
24
+ /** The files a relative `require` can mean, in lookup order. */
25
+ export declare const fileCandidates: (base: string) => ReadonlyArray<string>;
26
+ //# sourceMappingURL=targets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"targets.d.ts","sourceRoot":"","sources":["../../src/analyzer/targets.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAQ9C;;;;GAIG;AACH,eAAO,MAAM,aAAa,cAAe,MAAM,KAAG,MAAM,GAAG,SAU1D,CAAA;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CACxC;AAwBD,yFAAyF;AACzF,eAAO,MAAM,gBAAgB,cAAe,MAAM,KAAG,WAAW,GAAG,SACU,CAAA;AAE7E,yGAAyG;AACzG,eAAO,MAAM,gBAAgB,aAAc,aAAa,CAAC,MAAM,CAAC,KAAG,WAAW,GAAG,SAGhF,CAAA;AAED,eAAO,MAAM,WAAW,aAAc,aAAa,CAAC,MAAM,CAAC,KAAG,OAA0C,CAAA;AAYxG;;;;;GAKG;AACH,eAAO,MAAM,aAAa,cAAe,MAAM,aAAa,WAAW,GAAG,SAAS,KAAG,MAAM,GAAG,SAO9F,CAAA;AAYD,gEAAgE;AAChE,eAAO,MAAM,cAAc,SAAU,MAAM,KAAG,aAAa,CAAC,MAAM,CAKjE,CAAA"}
@@ -0,0 +1,84 @@
1
+ import { builtinModules } from "node:module";
2
+ import { NODE_MODULES } from "./paths.js";
3
+ const bareNodeBuiltins = new Set(builtinModules.filter((name) => !name.startsWith("node:")));
4
+ const prefixed = (specifier, prefix) => specifier.startsWith(prefix) && specifier.length > prefix.length ? specifier.slice(prefix.length) : undefined;
5
+ /**
6
+ * `node:fs` and `fs` give `Builtin(node, "fs")`, `bun:test` gives
7
+ * `Builtin(bun, "test")`. The prefix alone makes a built-in, as at runtime;
8
+ * a bare name must be in Node's own list, so `node:test` is one and `test` is not.
9
+ */
10
+ export const builtinTarget = (specifier) => {
11
+ const node = prefixed(specifier, "node:");
12
+ if (node !== undefined) {
13
+ return { _tag: "Builtin", runtime: "node", name: node };
14
+ }
15
+ const bun = prefixed(specifier, "bun:");
16
+ if (bun !== undefined) {
17
+ return { _tag: "Builtin", runtime: "bun", name: bun };
18
+ }
19
+ return bareNodeBuiltins.has(specifier) ? { _tag: "Builtin", runtime: "node", name: specifier } : undefined;
20
+ };
21
+ const isBareSpecifier = (specifier) => {
22
+ const first = specifier[0];
23
+ return (first !== undefined &&
24
+ first !== "." &&
25
+ first !== "/" &&
26
+ first !== "#" &&
27
+ first !== "~" &&
28
+ !specifier.includes(":") &&
29
+ !specifier.includes("\\"));
30
+ };
31
+ const splitPackage = (parts) => {
32
+ const scoped = parts[0]?.startsWith("@") === true;
33
+ const nameParts = parts.slice(0, scoped ? 2 : 1);
34
+ if (nameParts.length < (scoped ? 2 : 1) || nameParts.some((part) => part === "")) {
35
+ return undefined;
36
+ }
37
+ return { name: nameParts.join("/"), subpath: parts.slice(nameParts.length).filter((part) => part !== "") };
38
+ };
39
+ /** Scope-aware: `@scope/pkg/sub/path` is `@scope/pkg` with subpath `["sub", "path"]`. */
40
+ export const specifierPackage = (specifier) => isBareSpecifier(specifier) ? splitPackage(specifier.split("/")) : undefined;
41
+ /** The segment after the last `node_modules`, so nested and pnpm layouts both name the right package. */
42
+ export const installedPackage = (segments) => {
43
+ const index = segments.lastIndexOf(NODE_MODULES);
44
+ return index < 0 ? undefined : splitPackage(segments.slice(index + 1));
45
+ };
46
+ export const isInstalled = (segments) => segments.includes(NODE_MODULES);
47
+ /** DefinitelyTyped names `@a/b` as `@types/a__b`. */
48
+ const runtimeName = (name) => {
49
+ const typed = prefixed(name, "@types/");
50
+ if (typed === undefined) {
51
+ return name;
52
+ }
53
+ const separator = typed.indexOf("__");
54
+ return separator < 0 ? typed : `@${typed.slice(0, separator)}/${typed.slice(separator + 2)}`;
55
+ };
56
+ /**
57
+ * The specifier names the package when it is a package specifier for the
58
+ * package that was found: `picomatch` stays `picomatch` when the file is in
59
+ * `@types/picomatch`, and `react/jsx-runtime` keeps its subpath. Otherwise the
60
+ * file's own package decides, as for a path alias or a `#` import.
61
+ */
62
+ export const packageTarget = (specifier, installed) => {
63
+ const written = specifierPackage(specifier);
64
+ const found = installed === undefined || (written !== undefined && [installed.name, runtimeName(installed.name)].includes(written.name))
65
+ ? (written ?? installed)
66
+ : installed;
67
+ return found === undefined ? undefined : { _tag: "Package", name: found.name, subpath: found.subpath };
68
+ };
69
+ const sourceExtensions = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
70
+ /** `.js` in a specifier names the `.ts` file next to it. */
71
+ const extensionSubstitutes = [
72
+ [".js", [".ts", ".tsx"]],
73
+ [".jsx", [".tsx"]],
74
+ [".mjs", [".mts"]],
75
+ [".cjs", [".cts"]],
76
+ ];
77
+ /** The files a relative `require` can mean, in lookup order. */
78
+ export const fileCandidates = (base) => [
79
+ base,
80
+ ...extensionSubstitutes.flatMap(([from, to]) => (base.endsWith(from) ? to.map((ext) => base.slice(0, -from.length) + ext) : [])),
81
+ ...sourceExtensions.map((ext) => base + ext),
82
+ ...sourceExtensions.map((ext) => `${base}/index${ext}`),
83
+ ];
84
+ //# sourceMappingURL=targets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"targets.js","sourceRoot":"","sources":["../../src/analyzer/targets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /** The TypeScript adapter of the Analyzer. Contract: docs/architecture.md#analyzer. */
2
+ import { Effect, FileSystem, Path, Scope } from "effect";
3
+ import type { AnalyzerShape } from "./workspace.ts";
4
+ export declare const makeTypescript: Effect.Effect<AnalyzerShape, never, FileSystem.FileSystem | Path.Path | Scope.Scope>;
5
+ //# sourceMappingURL=typescript.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typescript.d.ts","sourceRoot":"","sources":["../../src/analyzer/typescript.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,OAAO,EAAE,MAAM,EAAQ,UAAU,EAAS,IAAI,EAAO,KAAK,EAAa,MAAM,QAAQ,CAAA;AAGrF,OAAO,KAAK,EAAE,aAAa,EAAa,MAAM,gBAAgB,CAAA;AAsI9D,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,KAAK,CAwN9G,CAAA"}
@@ -0,0 +1,221 @@
1
+ /** The TypeScript adapter of the Analyzer. Contract: docs/architecture.md#analyzer. */
2
+ import { Effect, Exit, FileSystem, Match, Path, Ref, Scope, Semaphore } from "effect";
3
+ import { API, DiagnosticCategory } from "typescript/unstable/async";
4
+ import { AnalyzerUnavailable, ProjectNotFound, ProjectParseFailed } from "./errors.js";
5
+ import { compareCodeUnits, isDeclarationFileName, isJsonFileName, NODE_MODULES, splitPath } from "./paths.js";
6
+ import { readSource } from "./source.js";
7
+ import { abandon, muteFailedWrites, serverExit } from "./server-exit.js";
8
+ import { builtinTarget, fileCandidates, installedPackage, isInstalled, packageTarget, specifierPackage } from "./targets.js";
9
+ const unavailable = (cause) => new AnalyzerUnavailable({ cause });
10
+ const attempt = (evaluate) => Effect.try({ try: evaluate, catch: unavailable });
11
+ const attemptPromise = (evaluate) => Effect.tryPromise({ try: evaluate, catch: unavailable });
12
+ /**
13
+ * The server starts on first use and stops with the layer's scope. A failure
14
+ * that makes the server unusable also stops it, so the next call starts a new one.
15
+ */
16
+ const makeServer = Effect.gen(function* () {
17
+ const layerScope = yield* Effect.scope;
18
+ const current = yield* Ref.make(undefined);
19
+ const lock = yield* Semaphore.make(1);
20
+ const start = Effect.gen(function* () {
21
+ const scope = yield* Scope.fork(layerScope);
22
+ let exitedServer = false;
23
+ const api = yield* Effect.acquireRelease(attempt(() => new API()), (started) => exitedServer ? Effect.sync(() => abandon(started)) : attemptPromise(() => started.close()).pipe(Effect.ignore)).pipe(Scope.provide(scope), Effect.tapError(() => Scope.close(scope, Exit.void)));
24
+ yield* attemptPromise(() => api.updateSnapshot().then((snapshot) => snapshot.dispose())).pipe(Effect.tapError(() => Scope.close(scope, Exit.void)));
25
+ muteFailedWrites(api);
26
+ const exited = serverExit(api);
27
+ void exited.then(() => {
28
+ exitedServer = true;
29
+ });
30
+ const lost = () => exited.then(() => {
31
+ throw new Error("TypeScript server exited");
32
+ });
33
+ /** A request to a server known to be dead fails without writing to it. */
34
+ const request = (evaluate) => exitedServer
35
+ ? Effect.fail(new AnalyzerUnavailable({ cause: new Error("TypeScript server exited") }))
36
+ : attemptPromise(() => Promise.race([evaluate(), lost()]));
37
+ const remote = { api, request };
38
+ const session = { remote, scope };
39
+ yield* Ref.set(current, session);
40
+ return session;
41
+ });
42
+ const stop = Effect.gen(function* () {
43
+ const session = yield* Ref.getAndSet(current, undefined);
44
+ if (session !== undefined) {
45
+ yield* Scope.close(session.scope, Exit.void);
46
+ }
47
+ });
48
+ /** A request cannot be taken back, so an interrupted analysis finishes before the next one starts. */
49
+ const use = (run) => lock.withPermit(Effect.gen(function* () {
50
+ const session = (yield* Ref.get(current)) ?? (yield* start);
51
+ return yield* run(session.remote);
52
+ }).pipe(Effect.uninterruptible, Effect.tapError(Match.type().pipe(Match.tag("AnalyzerUnavailable", () => stop), Match.orElse(() => Effect.void)))));
53
+ return { use };
54
+ });
55
+ const READ_CONCURRENCY = 16;
56
+ const normalize = (file) => file.replaceAll("\\", "/");
57
+ const joined = (path) => path.join("/");
58
+ const isRelative = (specifier, isAbsolute) => specifier === "." || specifier === ".." || specifier.startsWith("./") || specifier.startsWith("../") || isAbsolute(specifier);
59
+ export const makeTypescript = Effect.gen(function* () {
60
+ const fs = yield* FileSystem.FileSystem;
61
+ const path = yield* Path.Path;
62
+ const server = yield* makeServer;
63
+ const platform = (effect) => effect.pipe(Effect.mapError(unavailable));
64
+ const describeDiagnostic = (root) => (diagnostic) => {
65
+ const relative = diagnostic.fileName === undefined ? undefined : path.relative(root, diagnostic.fileName);
66
+ const file = relative === undefined ? undefined : relative.startsWith("..") ? diagnostic.fileName : relative;
67
+ return `${file === undefined ? "" : `${file}: `}TS${diagnostic.code}: ${diagnostic.text}`;
68
+ };
69
+ const loadProject = (remote, snapshot, root, tsconfig) => Effect.gen(function* () {
70
+ const project = snapshot.getProject(path.join(root, tsconfig));
71
+ if (project === undefined) {
72
+ return yield* unavailable(new Error(`TypeScript did not open ${tsconfig}`));
73
+ }
74
+ const errors = (yield* remote.request(() => project.program.getConfigFileParsingDiagnostics())).filter((diagnostic) => diagnostic.category === DiagnosticCategory.Error);
75
+ if (errors.length > 0) {
76
+ return yield* new ProjectParseFailed({ tsconfig, diagnostics: errors.map(describeDiagnostic(root)) });
77
+ }
78
+ return { tsconfig, project };
79
+ });
80
+ const locate = (root, tsconfig) => Effect.gen(function* () {
81
+ if (!(yield* platform(fs.exists(path.resolve(root, tsconfig))))) {
82
+ return yield* new ProjectNotFound({ tsconfig });
83
+ }
84
+ });
85
+ const sourceSet = (root, projects) => Effect.gen(function* () {
86
+ const entries = new Map();
87
+ for (const { project } of projects) {
88
+ const candidates = project.rootFiles.filter((fileName) => !isDeclarationFileName(fileName) && !isJsonFileName(fileName) && !isInstalled(splitPath(fileName)));
89
+ const real = yield* Effect.forEach(candidates, (fileName) => platform(fs.realPath(fileName)), { concurrency: 16 });
90
+ candidates.forEach((fileName, index) => {
91
+ const realPath = normalize(real[index] ?? fileName);
92
+ const relative = path.relative(root, realPath);
93
+ const segments = splitPath(relative);
94
+ const inside = segments.length > 0 && segments[0] !== ".." && !path.isAbsolute(relative);
95
+ if (inside && !isInstalled(segments) && !entries.has(realPath)) {
96
+ entries.set(realPath, { path: segments, programFileName: fileName, realPath, project });
97
+ }
98
+ });
99
+ }
100
+ return [...entries.values()].toSorted((left, right) => compareCodeUnits(joined(left.path), joined(right.path)));
101
+ });
102
+ const makeTargets = (entries, caseSensitive) => {
103
+ const fold = (file) => (caseSensitive ? normalize(file) : normalize(file).toLowerCase());
104
+ const files = new Map(entries.map((entry) => [fold(entry.realPath), entry.path]));
105
+ const probes = new Map();
106
+ const through = new Map();
107
+ const hasPackage = (directory, name) => Effect.gen(function* () {
108
+ const key = `${directory}\0${name}`;
109
+ const known = probes.get(key);
110
+ if (known !== undefined) {
111
+ return known;
112
+ }
113
+ const parent = path.dirname(directory);
114
+ const found = (yield* platform(fs.exists(path.join(directory, NODE_MODULES, name)))) ||
115
+ (parent !== directory && (yield* hasPackage(parent, name)));
116
+ probes.set(key, found);
117
+ return found;
118
+ });
119
+ const probedPackage = (specifier, directory) => Effect.gen(function* () {
120
+ const written = specifierPackage(specifier);
121
+ return written !== undefined && (yield* hasPackage(directory, written.name))
122
+ ? { _tag: "Package", name: written.name, subpath: written.subpath }
123
+ : { _tag: "Unresolved", specifier };
124
+ });
125
+ const relativeFile = (specifier, directory) => {
126
+ const hit = fileCandidates(path.resolve(directory, specifier)).find((candidate) => files.has(fold(candidate)));
127
+ const found = hit === undefined ? undefined : files.get(fold(hit));
128
+ return found === undefined ? { _tag: "Unresolved", specifier } : { _tag: "File", path: found };
129
+ };
130
+ const sourceFileAt = (modulePath) => {
131
+ const direct = files.get(fold(modulePath));
132
+ if (direct !== undefined || through.has(modulePath)) {
133
+ return Effect.succeed(direct ?? through.get(modulePath));
134
+ }
135
+ return fs.realPath(modulePath).pipe(Effect.map((real) => files.get(fold(real))), Effect.orElseSucceed(() => undefined), Effect.tap((found) => Effect.sync(() => through.set(modulePath, found))));
136
+ };
137
+ const moduleTarget = (specifier, module) => {
138
+ const unresolved = { _tag: "Unresolved", specifier };
139
+ const segments = splitPath(module.path);
140
+ return isInstalled(segments)
141
+ ? Effect.succeed(packageTarget(specifier, installedPackage(segments)) ?? unresolved)
142
+ : module.isFile
143
+ ? Effect.map(sourceFileAt(module.path), (found) => (found === undefined ? unresolved : { _tag: "File", path: found }))
144
+ : Effect.succeed(unresolved);
145
+ };
146
+ const orBuiltin = (specifier, otherwise) => {
147
+ const builtin = builtinTarget(specifier);
148
+ return builtin === undefined ? otherwise() : Effect.succeed(builtin);
149
+ };
150
+ const target = (dependency, directory) => Match.valueTags(dependency.resolution, {
151
+ Computed: () => Effect.succeed({ _tag: "Computed" }),
152
+ Module: (module) => orBuiltin(dependency.specifier, () => moduleTarget(dependency.specifier, module)),
153
+ Missing: () => orBuiltin(dependency.specifier, () => probedPackage(dependency.specifier, directory)),
154
+ Unchecked: () => orBuiltin(dependency.specifier, () => isRelative(dependency.specifier, path.isAbsolute)
155
+ ? Effect.succeed(relativeFile(dependency.specifier, directory))
156
+ : probedPackage(dependency.specifier, directory)),
157
+ });
158
+ return { target };
159
+ };
160
+ const read = (remote, entry) => remote.request(async () => {
161
+ const sourceFile = await entry.project.program.getSourceFile(entry.programFileName);
162
+ if (sourceFile === undefined) {
163
+ throw new Error(`TypeScript did not load ${entry.programFileName}`);
164
+ }
165
+ return { raw: await readSource(entry.project, sourceFile), caseSensitive: sourceFile.path === normalize(sourceFile.fileName) };
166
+ });
167
+ const assemble = (entry, raw, targets) => Effect.gen(function* () {
168
+ const directory = path.dirname(entry.realPath);
169
+ const dependencies = yield* Effect.forEach(raw.dependencies, (dependency) => Effect.map(targets.target(dependency, directory), (target) => ({
170
+ target,
171
+ kind: dependency.kind,
172
+ specifier: dependency.specifier,
173
+ location: dependency.location,
174
+ })));
175
+ return {
176
+ path: entry.path,
177
+ dependencies,
178
+ declarations: raw.declarations,
179
+ exports: raw.exports,
180
+ uses: raw.uses,
181
+ lines: raw.lines,
182
+ };
183
+ });
184
+ /**
185
+ * The server keeps tsconfig file lists and file contents between snapshots.
186
+ * Closing the projects, invalidating, and reporting the tsconfigs as changed
187
+ * makes it list and read everything again; the client's copies must go too.
188
+ */
189
+ const reset = ({ api, request }, configPaths) => request(async () => {
190
+ await (await api.updateSnapshot({ closeProjects: [...configPaths] })).dispose();
191
+ await (await api.updateSnapshot({ fileChanges: { invalidateAll: true } })).dispose();
192
+ await (await api.updateSnapshot({ fileChanges: { changed: [...configPaths] } })).dispose();
193
+ api.clearSourceFileCache();
194
+ });
195
+ const analyzeWith = (remote, root, tsconfigs) => {
196
+ const configPaths = tsconfigs.map((tsconfig) => path.join(root, tsconfig));
197
+ return Effect.acquireUseRelease(reset(remote, configPaths).pipe(Effect.andThen(remote.request(() => remote.api.updateSnapshot({ openProjects: [...configPaths] })))), (snapshot) => Effect.gen(function* () {
198
+ const projects = yield* Effect.forEach(tsconfigs, (tsconfig) => loadProject(remote, snapshot, root, tsconfig));
199
+ const entries = yield* sourceSet(root, projects);
200
+ const sources = yield* Effect.forEach(entries, (entry) => read(remote, entry), { concurrency: READ_CONCURRENCY });
201
+ const targets = makeTargets(entries, sources.every(({ caseSensitive }) => caseSensitive));
202
+ const files = yield* Effect.forEach(entries, (entry, index) => {
203
+ const source = sources[index];
204
+ return source === undefined
205
+ ? Effect.fail(unavailable(new Error(`no source read for ${entry.programFileName}`)))
206
+ : assemble(entry, source.raw, targets);
207
+ });
208
+ return { files };
209
+ }), (snapshot) => remote.request(async () => {
210
+ await snapshot.dispose();
211
+ await (await remote.api.updateSnapshot({ closeProjects: [...configPaths] })).dispose();
212
+ }).pipe(Effect.ignore));
213
+ };
214
+ const analyze = Effect.fn("Analyzer.typescript.analyze")(function* (workspace) {
215
+ yield* Effect.forEach(workspace.projects, (tsconfig) => locate(workspace.root, tsconfig));
216
+ const root = normalize(yield* platform(fs.realPath(workspace.root)));
217
+ return yield* server.use((remote) => analyzeWith(remote, root, workspace.projects));
218
+ });
219
+ return { analyze };
220
+ });
221
+ //# sourceMappingURL=typescript.js.map