@effect/language-service 0.28.3 → 0.30.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.
package/transform.js CHANGED
@@ -745,10 +745,6 @@ var none2 = () => none;
745
745
  var some2 = some;
746
746
  var isNone2 = isNone;
747
747
  var isSome2 = isSome;
748
- var match = /* @__PURE__ */ dual(2, (self, {
749
- onNone,
750
- onSome
751
- }) => isNone2(self) ? onNone() : onSome(self.value));
752
748
  var orElse = /* @__PURE__ */ dual(2, (self, that) => isNone2(self) ? that() : self);
753
749
  var fromNullable = (nullableValue) => nullableValue == null ? none2() : some2(nullableValue);
754
750
 
@@ -995,7 +991,7 @@ var MatchProto = {
995
991
  return this[args];
996
992
  }
997
993
  };
998
- var match2 = (fa, opts) => {
994
+ var match = (fa, opts) => {
999
995
  const nano = Object.create(MatchProto);
1000
996
  nano[args] = fa;
1001
997
  nano[contA] = opts.onSuccess;
@@ -1018,7 +1014,7 @@ var ProvideServiceProto = {
1018
1014
  ...fiber._services,
1019
1015
  [tag.key]: value
1020
1016
  };
1021
- return match2(fa, {
1017
+ return match(fa, {
1022
1018
  onSuccess: (_) => {
1023
1019
  fiber._services = prevServices;
1024
1020
  return succeed(_);
@@ -1061,7 +1057,7 @@ var CachedProto = {
1061
1057
  fiber._cache[type] = cache;
1062
1058
  const cached2 = cache.get(key);
1063
1059
  if (cached2) return cached2;
1064
- return match2(fa, {
1060
+ return match(fa, {
1065
1061
  onSuccess: (_) => {
1066
1062
  cache.set(key, succeed(_));
1067
1063
  return succeed(_);
@@ -1137,44 +1133,50 @@ function parse(config) {
1137
1133
  var TypeScriptApi = Tag("TypeScriptApi");
1138
1134
  var TypeScriptProgram = Tag("TypeScriptProgram");
1139
1135
  var ChangeTracker = Tag("ChangeTracker");
1140
- function parsePackageContentNameAndVersionFromScope(v) {
1141
- if (!isObject(v)) return;
1142
- if (!hasProperty(v, "packageJsonScope")) return;
1143
- if (!v.packageJsonScope) return;
1144
- const packageJsonScope = v.packageJsonScope;
1145
- if (!hasProperty(packageJsonScope, "contents")) return;
1146
- if (!hasProperty(packageJsonScope.contents, "packageJsonContent")) return;
1147
- const packageJsonContent = packageJsonScope.contents.packageJsonContent;
1148
- if (!hasProperty(packageJsonContent, "name")) return;
1149
- if (!hasProperty(packageJsonContent, "version")) return;
1150
- if (!hasProperty(packageJsonScope, "packageDirectory")) return;
1151
- if (!isString(packageJsonScope.packageDirectory)) return;
1152
- const { name, version } = packageJsonContent;
1153
- if (!isString(name)) return;
1154
- if (!isString(version)) return;
1155
- const hasEffectInPeerDependencies = hasProperty(packageJsonContent, "peerDependencies") && isObject(packageJsonContent.peerDependencies) && hasProperty(packageJsonContent.peerDependencies, "effect");
1156
- const referencedPackages = Object.keys({
1157
- ...hasProperty(packageJsonContent, "dependencies") && isObject(packageJsonContent.dependencies) ? packageJsonContent.dependencies : {},
1158
- ...hasProperty(packageJsonContent, "peerDependencies") && isObject(packageJsonContent.peerDependencies) ? packageJsonContent.peerDependencies : {},
1159
- ...hasProperty(packageJsonContent, "devDependencies") && isObject(packageJsonContent.devDependencies) ? packageJsonContent.devDependencies : {}
1160
- });
1161
- const exportsKeys = Object.keys(
1162
- hasProperty(packageJsonContent, "exports") && isObject(packageJsonContent.exports) ? packageJsonContent.exports : {}
1163
- );
1164
- return {
1165
- name: name.toLowerCase(),
1166
- version: version.toLowerCase(),
1167
- hasEffectInPeerDependencies,
1168
- contents: packageJsonContent,
1169
- packageDirectory: packageJsonScope.packageDirectory,
1170
- referencedPackages,
1171
- exportsKeys
1172
- };
1173
- }
1174
- var resolveModulePattern = fn("resolveModulePattern")(
1175
- function* (sourceFile, pattern) {
1136
+
1137
+ // src/core/TypeScriptUtils.ts
1138
+ var TypeScriptUtils = Tag("TypeScriptUtils");
1139
+ var nanoLayer = (fa) => pipe(
1140
+ service(TypeScriptApi),
1141
+ flatMap2((ts) => pipe(fa, provideService(TypeScriptUtils, makeTypeScriptUtils(ts))))
1142
+ );
1143
+ function makeTypeScriptUtils(ts) {
1144
+ function parsePackageContentNameAndVersionFromScope(v) {
1145
+ if (!isObject(v)) return;
1146
+ if (!hasProperty(v, "packageJsonScope")) return;
1147
+ if (!v.packageJsonScope) return;
1148
+ const packageJsonScope = v.packageJsonScope;
1149
+ if (!hasProperty(packageJsonScope, "contents")) return;
1150
+ if (!hasProperty(packageJsonScope.contents, "packageJsonContent")) return;
1151
+ const packageJsonContent = packageJsonScope.contents.packageJsonContent;
1152
+ if (!hasProperty(packageJsonContent, "name")) return;
1153
+ if (!hasProperty(packageJsonContent, "version")) return;
1154
+ if (!hasProperty(packageJsonScope, "packageDirectory")) return;
1155
+ if (!isString(packageJsonScope.packageDirectory)) return;
1156
+ const { name, version } = packageJsonContent;
1157
+ if (!isString(name)) return;
1158
+ if (!isString(version)) return;
1159
+ const hasEffectInPeerDependencies = hasProperty(packageJsonContent, "peerDependencies") && isObject(packageJsonContent.peerDependencies) && hasProperty(packageJsonContent.peerDependencies, "effect");
1160
+ const referencedPackages = Object.keys({
1161
+ ...hasProperty(packageJsonContent, "dependencies") && isObject(packageJsonContent.dependencies) ? packageJsonContent.dependencies : {},
1162
+ ...hasProperty(packageJsonContent, "peerDependencies") && isObject(packageJsonContent.peerDependencies) ? packageJsonContent.peerDependencies : {},
1163
+ ...hasProperty(packageJsonContent, "devDependencies") && isObject(packageJsonContent.devDependencies) ? packageJsonContent.devDependencies : {}
1164
+ });
1165
+ const exportsKeys = Object.keys(
1166
+ hasProperty(packageJsonContent, "exports") && isObject(packageJsonContent.exports) ? packageJsonContent.exports : {}
1167
+ );
1168
+ return {
1169
+ name: name.toLowerCase(),
1170
+ version: version.toLowerCase(),
1171
+ hasEffectInPeerDependencies,
1172
+ contents: packageJsonContent,
1173
+ packageDirectory: packageJsonScope.packageDirectory,
1174
+ referencedPackages,
1175
+ exportsKeys
1176
+ };
1177
+ }
1178
+ function resolveModulePattern(sourceFile, pattern) {
1176
1179
  if (pattern.indexOf("*") === -1) return [pattern.toLowerCase()];
1177
- const ts = yield* service(TypeScriptApi);
1178
1180
  const packageJsonScope = parsePackageContentNameAndVersionFromScope(sourceFile);
1179
1181
  const referencedPackages = [];
1180
1182
  for (const statement of sourceFile.statements) {
@@ -1193,19 +1195,338 @@ var resolveModulePattern = fn("resolveModulePattern")(
1193
1195
  )
1194
1196
  );
1195
1197
  }
1196
- );
1197
- function makeGetModuleSpecifier(ts) {
1198
- if (!(hasProperty(ts, "moduleSpecifiers") && hasProperty(ts.moduleSpecifiers, "getModuleSpecifier") && isFunction2(ts.moduleSpecifiers.getModuleSpecifier))) return;
1199
- const _internal = ts.moduleSpecifiers.getModuleSpecifier;
1200
- return (compilerOptions, importingSourceFile, importingSourceFileName, toFileName, host, options) => {
1201
- return _internal(
1202
- compilerOptions,
1203
- importingSourceFile,
1204
- importingSourceFileName,
1205
- toFileName,
1206
- host,
1207
- options
1198
+ function makeGetModuleSpecifier() {
1199
+ if (!(hasProperty(ts, "moduleSpecifiers") && hasProperty(ts.moduleSpecifiers, "getModuleSpecifier") && isFunction2(ts.moduleSpecifiers.getModuleSpecifier))) return;
1200
+ const _internal = ts.moduleSpecifiers.getModuleSpecifier;
1201
+ return (compilerOptions, importingSourceFile, importingSourceFileName, toFileName, host, options) => {
1202
+ return _internal(
1203
+ compilerOptions,
1204
+ importingSourceFile,
1205
+ importingSourceFileName,
1206
+ toFileName,
1207
+ host,
1208
+ options
1209
+ );
1210
+ };
1211
+ }
1212
+ function findNodeWithLeadingCommentAtPosition(sourceFile, position) {
1213
+ const sourceText = sourceFile.text;
1214
+ let result;
1215
+ function find(node) {
1216
+ const leading = ts.getLeadingCommentRanges(sourceText, node.getFullStart());
1217
+ if (leading) {
1218
+ for (const commentRange of leading) {
1219
+ if (commentRange.pos <= position && position < commentRange.end) {
1220
+ result = { node, commentRange };
1221
+ return;
1222
+ }
1223
+ }
1224
+ }
1225
+ if (node.getFullStart() <= position && position < node.getEnd()) {
1226
+ node.forEachChild(find);
1227
+ }
1228
+ }
1229
+ find(sourceFile);
1230
+ return result;
1231
+ }
1232
+ function collectSelfAndAncestorNodesInRange(node, textRange) {
1233
+ let result = empty();
1234
+ let parent = node;
1235
+ while (parent) {
1236
+ if (parent.end >= textRange.end) {
1237
+ result = pipe(result, append(parent));
1238
+ }
1239
+ parent = parent.parent;
1240
+ }
1241
+ return result;
1242
+ }
1243
+ function findNodeAtPosition(sourceFile, position) {
1244
+ function find(node) {
1245
+ if (position >= node.getStart() && position < node.getEnd()) {
1246
+ return ts.forEachChild(node, find) || node;
1247
+ }
1248
+ return void 0;
1249
+ }
1250
+ return find(sourceFile);
1251
+ }
1252
+ function findNodeAtPositionIncludingTrivia(sourceFile, position) {
1253
+ function find(node) {
1254
+ if (position >= node.pos && position < node.end) {
1255
+ return ts.forEachChild(node, find) || node;
1256
+ }
1257
+ return void 0;
1258
+ }
1259
+ return find(sourceFile);
1260
+ }
1261
+ function getAncestorNodesInRange(sourceFile, textRange) {
1262
+ const nodeAtPosition = findNodeAtPosition(sourceFile, textRange.pos);
1263
+ if (!nodeAtPosition) return empty();
1264
+ return collectSelfAndAncestorNodesInRange(nodeAtPosition, textRange);
1265
+ }
1266
+ function getCommentAtPosition(sourceFile, pos) {
1267
+ const token = findNodeAtPositionIncludingTrivia(sourceFile, pos);
1268
+ if (token === void 0 || token.kind === ts.SyntaxKind.JsxText || pos >= token.end - (ts.tokenToString(token.kind) || "").length) {
1269
+ return;
1270
+ }
1271
+ const startPos = token.pos === 0 ? (ts.getShebang(sourceFile.text) || "").length : token.pos;
1272
+ if (startPos === 0) return;
1273
+ const result = ts.forEachTrailingCommentRange(sourceFile.text, startPos, isCommentInRange, pos) || ts.forEachLeadingCommentRange(sourceFile.text, startPos, isCommentInRange, pos);
1274
+ return result;
1275
+ }
1276
+ function isCommentInRange(pos, end, kind, _nl, at) {
1277
+ return at >= pos && at < end ? { pos, end, kind } : void 0;
1278
+ }
1279
+ function toTextRange(positionOrRange) {
1280
+ return typeof positionOrRange === "number" ? { end: positionOrRange, pos: positionOrRange } : positionOrRange;
1281
+ }
1282
+ function isNodeInRange(textRange) {
1283
+ return (node) => node.pos <= textRange.pos && node.end >= textRange.end;
1284
+ }
1285
+ function transformAsyncAwaitToEffectGen(node, effectModuleName, onAwait) {
1286
+ function visitor(_) {
1287
+ if (ts.isAwaitExpression(_)) {
1288
+ const expression = ts.visitEachChild(_.expression, visitor, ts.nullTransformationContext);
1289
+ return ts.factory.createYieldExpression(
1290
+ ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
1291
+ onAwait(expression)
1292
+ );
1293
+ }
1294
+ return ts.visitEachChild(_, visitor, ts.nullTransformationContext);
1295
+ }
1296
+ const generatorBody = visitor(node.body);
1297
+ const effectGenCallExp = createEffectGenCallExpression(effectModuleName, generatorBody);
1298
+ let currentFlags = ts.getCombinedModifierFlags(node);
1299
+ currentFlags &= ~ts.ModifierFlags.Async;
1300
+ const newModifiers = ts.factory.createModifiersFromModifierFlags(currentFlags);
1301
+ if (ts.isArrowFunction(node)) {
1302
+ return ts.factory.createArrowFunction(
1303
+ newModifiers,
1304
+ node.typeParameters,
1305
+ node.parameters,
1306
+ void 0,
1307
+ node.equalsGreaterThanToken,
1308
+ effectGenCallExp
1309
+ );
1310
+ }
1311
+ const newBody = ts.factory.createBlock([
1312
+ ts.factory.createReturnStatement(effectGenCallExp)
1313
+ ]);
1314
+ if (ts.isFunctionDeclaration(node)) {
1315
+ return ts.factory.createFunctionDeclaration(
1316
+ newModifiers,
1317
+ node.asteriskToken,
1318
+ node.name,
1319
+ node.typeParameters,
1320
+ node.parameters,
1321
+ void 0,
1322
+ newBody
1323
+ );
1324
+ }
1325
+ return ts.factory.createFunctionExpression(
1326
+ newModifiers,
1327
+ node.asteriskToken,
1328
+ node.name,
1329
+ node.typeParameters,
1330
+ node.parameters,
1331
+ void 0,
1332
+ newBody
1333
+ );
1334
+ }
1335
+ function findImportedModuleIdentifier(sourceFile, test) {
1336
+ for (const statement of sourceFile.statements) {
1337
+ if (!ts.isImportDeclaration(statement)) continue;
1338
+ const importClause = statement.importClause;
1339
+ if (!importClause) continue;
1340
+ const namedBindings = importClause.namedBindings;
1341
+ if (!namedBindings) continue;
1342
+ if (ts.isNamespaceImport(namedBindings)) {
1343
+ if (test(namedBindings.name, statement.moduleSpecifier, none2())) {
1344
+ return namedBindings.name.text;
1345
+ }
1346
+ } else if (ts.isNamedImports(namedBindings)) {
1347
+ for (const importSpecifier of namedBindings.elements) {
1348
+ const importProperty = fromNullable(importSpecifier.propertyName).pipe(
1349
+ orElse(() => some2(importSpecifier.name))
1350
+ );
1351
+ if (test(importSpecifier.name, statement.moduleSpecifier, importProperty)) {
1352
+ return importSpecifier.name.text;
1353
+ }
1354
+ }
1355
+ }
1356
+ }
1357
+ }
1358
+ function findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, packageName, moduleName) {
1359
+ return findImportedModuleIdentifier(
1360
+ sourceFile,
1361
+ (_, fromModule, importProperty) => {
1362
+ if (isNone2(importProperty) && ts.isStringLiteral(fromModule) && fromModule.text === packageName + "/" + moduleName) {
1363
+ return true;
1364
+ }
1365
+ if (isSome2(importProperty) && ts.isIdentifier(importProperty.value) && importProperty.value.text === moduleName && ts.isStringLiteral(fromModule) && fromModule.text === packageName) {
1366
+ return true;
1367
+ }
1368
+ return false;
1369
+ }
1208
1370
  );
1371
+ }
1372
+ function simplifyTypeNode(typeNode) {
1373
+ function collectCallable(typeNode2) {
1374
+ if (ts.isParenthesizedTypeNode(typeNode2)) return collectCallable(typeNode2.type);
1375
+ if (ts.isFunctionTypeNode(typeNode2)) {
1376
+ return some2([
1377
+ ts.factory.createCallSignature(typeNode2.typeParameters, typeNode2.parameters, typeNode2.type)
1378
+ ]);
1379
+ }
1380
+ if (ts.isTypeLiteralNode(typeNode2)) {
1381
+ const allCallSignatures = typeNode2.members.every(ts.isCallSignatureDeclaration);
1382
+ if (allCallSignatures) {
1383
+ return some2(typeNode2.members);
1384
+ }
1385
+ }
1386
+ if (ts.isIntersectionTypeNode(typeNode2)) {
1387
+ const members = typeNode2.types.map((node) => collectCallable(node));
1388
+ if (members.every(isSome2)) {
1389
+ return some2(members.map((_) => isSome2(_) ? _.value : []).flat());
1390
+ }
1391
+ }
1392
+ return none2();
1393
+ }
1394
+ const callSignatures = collectCallable(typeNode);
1395
+ if (isSome2(callSignatures) && callSignatures.value.length > 1) {
1396
+ return ts.factory.createTypeLiteralNode(callSignatures.value);
1397
+ }
1398
+ return typeNode;
1399
+ }
1400
+ function tryPreserveDeclarationSemantics(nodeToReplace, node) {
1401
+ if (!ts.isExpression(node)) return node;
1402
+ if (ts.isFunctionDeclaration(nodeToReplace)) {
1403
+ if (!nodeToReplace.name) return node;
1404
+ return ts.factory.createVariableStatement(
1405
+ nodeToReplace.modifiers,
1406
+ ts.factory.createVariableDeclarationList(
1407
+ [ts.factory.createVariableDeclaration(
1408
+ nodeToReplace.name,
1409
+ void 0,
1410
+ void 0,
1411
+ node
1412
+ )],
1413
+ ts.NodeFlags.Const
1414
+ )
1415
+ );
1416
+ } else if (ts.isMethodDeclaration(nodeToReplace)) {
1417
+ return ts.factory.createPropertyDeclaration(
1418
+ nodeToReplace.modifiers,
1419
+ nodeToReplace.name,
1420
+ void 0,
1421
+ void 0,
1422
+ node
1423
+ );
1424
+ }
1425
+ return node;
1426
+ }
1427
+ function parseAccessedExpressionForCompletion(sourceFile, position) {
1428
+ const precedingToken = ts.findPrecedingToken(position, sourceFile, void 0, true);
1429
+ if (!precedingToken) return;
1430
+ let accessedObject = precedingToken;
1431
+ let replacementSpan = ts.createTextSpan(position, 0);
1432
+ let outerNode = precedingToken;
1433
+ if (ts.isIdentifier(precedingToken) && precedingToken.parent && ts.isPropertyAccessExpression(precedingToken.parent)) {
1434
+ replacementSpan = ts.createTextSpan(
1435
+ precedingToken.parent.getStart(sourceFile),
1436
+ precedingToken.end - precedingToken.parent.getStart(sourceFile)
1437
+ );
1438
+ accessedObject = precedingToken.parent.expression;
1439
+ outerNode = precedingToken.parent;
1440
+ } else if (ts.isToken(precedingToken) && precedingToken.kind === ts.SyntaxKind.DotToken && ts.isPropertyAccessExpression(precedingToken.parent)) {
1441
+ replacementSpan = ts.createTextSpan(
1442
+ precedingToken.parent.getStart(sourceFile),
1443
+ precedingToken.end - precedingToken.parent.getStart(sourceFile)
1444
+ );
1445
+ accessedObject = precedingToken.parent.expression;
1446
+ outerNode = precedingToken.parent;
1447
+ } else if (ts.isIdentifier(precedingToken) && precedingToken.parent) {
1448
+ replacementSpan = ts.createTextSpan(
1449
+ precedingToken.getStart(sourceFile),
1450
+ precedingToken.end - precedingToken.getStart(sourceFile)
1451
+ );
1452
+ accessedObject = precedingToken;
1453
+ outerNode = precedingToken;
1454
+ } else {
1455
+ return;
1456
+ }
1457
+ return { accessedObject, outerNode, replacementSpan };
1458
+ }
1459
+ function parseDataForExtendsClassCompletion(sourceFile, position) {
1460
+ const maybeInfos = parseAccessedExpressionForCompletion(sourceFile, position);
1461
+ if (!maybeInfos) return;
1462
+ const { accessedObject, outerNode, replacementSpan } = maybeInfos;
1463
+ if (!ts.isIdentifier(accessedObject)) return;
1464
+ let classDeclaration = outerNode.parent;
1465
+ while (ts.isExpressionWithTypeArguments(classDeclaration) || ts.isHeritageClause(classDeclaration)) {
1466
+ if (!classDeclaration.parent) break;
1467
+ classDeclaration = classDeclaration.parent;
1468
+ }
1469
+ if (!ts.isClassDeclaration(classDeclaration)) return;
1470
+ if (!classDeclaration.name) return;
1471
+ return {
1472
+ accessedObject,
1473
+ classDeclaration,
1474
+ className: classDeclaration.name,
1475
+ replacementSpan
1476
+ };
1477
+ }
1478
+ function createEffectGenCallExpression(effectModuleIdentifierName, node) {
1479
+ const generator = ts.factory.createFunctionExpression(
1480
+ void 0,
1481
+ ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
1482
+ void 0,
1483
+ [],
1484
+ [],
1485
+ void 0,
1486
+ node
1487
+ // NOTE(mattia): intended, to use same routine for both ConciseBody and Body
1488
+ );
1489
+ return ts.factory.createCallExpression(
1490
+ ts.factory.createPropertyAccessExpression(
1491
+ ts.factory.createIdentifier(effectModuleIdentifierName),
1492
+ "gen"
1493
+ ),
1494
+ void 0,
1495
+ [generator]
1496
+ );
1497
+ }
1498
+ function createEffectGenCallExpressionWithBlock(effectModuleIdentifierName, statement) {
1499
+ return createEffectGenCallExpression(
1500
+ effectModuleIdentifierName,
1501
+ ts.factory.createBlock(isArray(statement) ? statement : [statement], false)
1502
+ );
1503
+ }
1504
+ function createReturnYieldStarStatement(expr) {
1505
+ return ts.factory.createReturnStatement(
1506
+ ts.factory.createYieldExpression(
1507
+ ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
1508
+ expr
1509
+ )
1510
+ );
1511
+ }
1512
+ return {
1513
+ findNodeAtPositionIncludingTrivia,
1514
+ parsePackageContentNameAndVersionFromScope,
1515
+ resolveModulePattern,
1516
+ findNodeWithLeadingCommentAtPosition,
1517
+ getCommentAtPosition,
1518
+ getAncestorNodesInRange,
1519
+ toTextRange,
1520
+ isNodeInRange,
1521
+ transformAsyncAwaitToEffectGen,
1522
+ findImportedModuleIdentifierByPackageAndNameOrBarrel,
1523
+ simplifyTypeNode,
1524
+ tryPreserveDeclarationSemantics,
1525
+ parseDataForExtendsClassCompletion,
1526
+ createEffectGenCallExpressionWithBlock,
1527
+ createReturnYieldStarStatement,
1528
+ makeGetModuleSpecifier,
1529
+ parseAccessedExpressionForCompletion
1209
1530
  };
1210
1531
  }
1211
1532
 
@@ -1213,6 +1534,9 @@ function makeGetModuleSpecifier(ts) {
1213
1534
  var RefactorNotApplicableError = class {
1214
1535
  _tag = "@effect/language-service/RefactorNotApplicableError";
1215
1536
  };
1537
+ function createRefactor(definition) {
1538
+ return definition;
1539
+ }
1216
1540
  function createDiagnostic(definition) {
1217
1541
  return definition;
1218
1542
  }
@@ -1275,27 +1599,8 @@ var getCompletionsAtPosition = fn("LSP.getCompletionsAtPosition")(function* (com
1275
1599
  var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
1276
1600
  function* (sourceFile) {
1277
1601
  const ts = yield* service(TypeScriptApi);
1602
+ const tsUtils = yield* service(TypeScriptUtils);
1278
1603
  const pluginOptions = yield* service(LanguageServicePluginOptions);
1279
- function findNodeWithLeadingCommentAtPosition(position) {
1280
- const sourceText = sourceFile.text;
1281
- let result;
1282
- function find(node) {
1283
- const leading = ts.getLeadingCommentRanges(sourceText, node.getFullStart());
1284
- if (leading) {
1285
- for (const r of leading) {
1286
- if (r.pos <= position && position < r.end) {
1287
- result = node;
1288
- return;
1289
- }
1290
- }
1291
- }
1292
- if (node.getFullStart() <= position && position < node.getEnd()) {
1293
- node.forEachChild(find);
1294
- }
1295
- }
1296
- find(sourceFile);
1297
- return result;
1298
- }
1299
1604
  function findParentStatementForDisableNextLine(node) {
1300
1605
  let result;
1301
1606
  function find(node2) {
@@ -1313,10 +1618,10 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
1313
1618
  const sectionOverrides = {};
1314
1619
  const skippedRules = [];
1315
1620
  const regex = /@effect-diagnostics(-next-line)?((?:\s[a-zA-Z0-9/]+:(?:off|warning|error|message|suggestion|skip-file))+)?/gm;
1316
- let match3;
1317
- while ((match3 = regex.exec(sourceFile.text)) !== null) {
1318
- const nextLineCaptureGroup = match3[1];
1319
- const rulesCaptureGroup = match3[2];
1621
+ let match2;
1622
+ while ((match2 = regex.exec(sourceFile.text)) !== null) {
1623
+ const nextLineCaptureGroup = match2[1];
1624
+ const rulesCaptureGroup = match2[2];
1320
1625
  if (rulesCaptureGroup) {
1321
1626
  const trimmedRuleString = rulesCaptureGroup.trim();
1322
1627
  if (trimmedRuleString) {
@@ -1328,19 +1633,19 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
1328
1633
  if (ruleLevel === "skip-file") skippedRules.push(ruleName);
1329
1634
  const isOverrideNextLine = nextLineCaptureGroup && nextLineCaptureGroup.trim().toLowerCase() === "-next-line";
1330
1635
  if (isOverrideNextLine) {
1331
- const node = findNodeWithLeadingCommentAtPosition(match3.index);
1332
- if (node) {
1636
+ const foundNode = tsUtils.findNodeWithLeadingCommentAtPosition(sourceFile, match2.index);
1637
+ if (foundNode) {
1333
1638
  lineOverrides[ruleName] = lineOverrides[ruleName] || [];
1334
1639
  lineOverrides[ruleName].unshift({
1335
- pos: node.getFullStart(),
1336
- end: node.end,
1640
+ pos: foundNode.node.getFullStart(),
1641
+ end: foundNode.node.end,
1337
1642
  level: ruleLevel
1338
1643
  });
1339
1644
  }
1340
1645
  } else {
1341
1646
  sectionOverrides[ruleName] = sectionOverrides[ruleName] || [];
1342
1647
  sectionOverrides[ruleName].unshift({
1343
- pos: match3.index,
1648
+ pos: match2.index,
1344
1649
  level: ruleLevel
1345
1650
  });
1346
1651
  }
@@ -1355,7 +1660,7 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
1355
1660
  message: ts.DiagnosticCategory.Message,
1356
1661
  suggestion: ts.DiagnosticCategory.Suggestion
1357
1662
  };
1358
- const execute = fn("LSP.ruleExecutor")(function* (rule) {
1663
+ const execute = (rule) => gen(function* () {
1359
1664
  const diagnostics2 = [];
1360
1665
  const codeFixes = [];
1361
1666
  const ruleNameLowered = rule.name.toLowerCase();
@@ -1364,13 +1669,13 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
1364
1669
  if (defaultLevel === "off" && (lineOverrides[ruleNameLowered] || sectionOverrides[ruleNameLowered] || []).length === 0) {
1365
1670
  return { diagnostics: diagnostics2, codeFixes };
1366
1671
  }
1367
- const fixByDisableNextLine = (_) => ({
1672
+ const fixByDisableNextLine = (node) => ({
1368
1673
  fixName: rule.name + "_skipNextLine",
1369
1674
  description: "Disable " + rule.name + " for this line",
1370
1675
  apply: flatMap2(
1371
1676
  service(ChangeTracker),
1372
- (changeTracker) => sync(() => {
1373
- const disableAtNode = findParentStatementForDisableNextLine(_.node);
1677
+ (changeTracker) => gen(function* () {
1678
+ const disableAtNode = findParentStatementForDisableNextLine(node);
1374
1679
  const { line } = ts.getLineAndCharacterOfPosition(sourceFile, disableAtNode.getStart());
1375
1680
  changeTracker.insertCommentBeforeLine(
1376
1681
  sourceFile,
@@ -1398,29 +1703,30 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
1398
1703
  };
1399
1704
  const applicableDiagnostics = [];
1400
1705
  yield* rule.apply(sourceFile, (entry) => {
1706
+ const range = "getEnd" in entry.location ? { pos: entry.location.getStart(sourceFile), end: entry.location.getEnd() } : entry.location;
1707
+ const node = "getEnd" in entry.location ? entry.location : tsUtils.findNodeAtPositionIncludingTrivia(sourceFile, entry.location.pos);
1401
1708
  applicableDiagnostics.push({
1402
- ...entry,
1403
- fixes: entry.fixes.concat([fixByDisableNextLine(entry), fixByDisableEntireFile])
1709
+ range,
1710
+ messageText: entry.messageText,
1711
+ fixes: entry.fixes.concat(node ? [fixByDisableNextLine(node)] : []).concat([fixByDisableEntireFile])
1404
1712
  });
1405
1713
  });
1406
1714
  for (const emitted of applicableDiagnostics.slice(0)) {
1407
1715
  let newLevel = defaultLevel;
1408
1716
  const lineOverride = (lineOverrides[ruleNameLowered] || []).find(
1409
- (_) => _.pos < emitted.node.getStart(sourceFile) && _.end >= emitted.node.getEnd()
1717
+ (_) => _.pos < emitted.range.pos && _.end >= emitted.range.end
1410
1718
  );
1411
1719
  if (lineOverride) {
1412
1720
  newLevel = lineOverride.level;
1413
1721
  } else {
1414
- const sectionOverride = (sectionOverrides[ruleNameLowered] || []).find(
1415
- (_) => _.pos < emitted.node.getStart(sourceFile)
1416
- );
1722
+ const sectionOverride = (sectionOverrides[ruleNameLowered] || []).find((_) => _.pos < emitted.range.pos);
1417
1723
  if (sectionOverride) newLevel = sectionOverride.level;
1418
1724
  }
1419
1725
  if (!(newLevel in levelToDiagnosticCategory)) continue;
1420
1726
  diagnostics2.push({
1421
1727
  file: sourceFile,
1422
- start: emitted.node.getStart(sourceFile),
1423
- length: emitted.node.getEnd() - emitted.node.getStart(sourceFile),
1728
+ start: emitted.range.pos,
1729
+ length: emitted.range.end - emitted.range.pos,
1424
1730
  messageText: emitted.messageText,
1425
1731
  category: levelToDiagnosticCategory[newLevel],
1426
1732
  code: rule.code,
@@ -1430,8 +1736,8 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
1430
1736
  codeFixes.push({
1431
1737
  ...fix,
1432
1738
  code: rule.code,
1433
- start: emitted.node.getStart(sourceFile),
1434
- end: emitted.node.getEnd()
1739
+ start: emitted.range.pos,
1740
+ end: emitted.range.end
1435
1741
  });
1436
1742
  }
1437
1743
  }
@@ -1440,15 +1746,85 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
1440
1746
  return { execute };
1441
1747
  }
1442
1748
  );
1749
+ var cyrb53 = (str, seed = 0) => {
1750
+ let h1 = 3735928559 ^ seed, h2 = 1103547991 ^ seed;
1751
+ for (let i = 0, ch; i < str.length; i++) {
1752
+ ch = str.charCodeAt(i);
1753
+ h1 = Math.imul(h1 ^ ch, 2654435761);
1754
+ h2 = Math.imul(h2 ^ ch, 1597334677);
1755
+ }
1756
+ h1 = Math.imul(h1 ^ h1 >>> 16, 2246822507);
1757
+ h1 ^= Math.imul(h2 ^ h2 >>> 13, 3266489909);
1758
+ h2 = Math.imul(h2 ^ h2 >>> 16, 2246822507);
1759
+ h2 ^= Math.imul(h1 ^ h1 >>> 13, 3266489909);
1760
+ return (h2 >>> 0).toString(16).padStart(8, "0") + (h1 >>> 0).toString(16).padStart(8, "0");
1761
+ };
1762
+ var CodegenNotApplicableError = class {
1763
+ constructor(cause) {
1764
+ this.cause = cause;
1765
+ }
1766
+ _tag = "@effect/language-service/CodegenNotApplicableError";
1767
+ };
1768
+ function createCodegen(definition) {
1769
+ return definition;
1770
+ }
1771
+ var getCodegensForSourceFile = fn("LSP.getApplicableCodegens")(function* (codegens2, sourceFile) {
1772
+ const tsUtils = yield* service(TypeScriptUtils);
1773
+ const result = [];
1774
+ const regex = /@effect-codegens((?:\s[a-zA-Z0-9]+(?::(?:[a-zA-Z0-9]+))?)+)+/gmid;
1775
+ let match2;
1776
+ while ((match2 = regex.exec(sourceFile.text)) !== null) {
1777
+ const pos = match2.indices?.[0]?.[0];
1778
+ if (!pos) continue;
1779
+ const commentRange = tsUtils.getCommentAtPosition(sourceFile, pos);
1780
+ if (!commentRange) continue;
1781
+ const commentText = sourceFile.text.slice(pos, commentRange.end);
1782
+ const codegenRegex = /(\s+)(\w+)(?::(\w+))?/gmi;
1783
+ let codegenMatch;
1784
+ while ((codegenMatch = codegenRegex.exec(commentText)) !== null) {
1785
+ const whitespace = codegenMatch[1] || "";
1786
+ const codegenName = codegenMatch[2] || "";
1787
+ const codegenHash = codegenMatch[3] || "";
1788
+ const range = {
1789
+ pos: codegenMatch.index + pos + whitespace.length,
1790
+ end: codegenMatch.index + pos + codegenMatch[0].length
1791
+ };
1792
+ const codegen = codegens2.find((codegen2) => codegen2.name === codegenName);
1793
+ if (!codegen) continue;
1794
+ result.push({ codegen, hash: codegenHash, range });
1795
+ }
1796
+ }
1797
+ return result;
1798
+ });
1799
+ var getEditsForCodegen = fn("LSP.getEditsForCodegen")(function* (codegens2, sourceFile, textRange) {
1800
+ const applicableCodegens = yield* getCodegensForSourceFile(codegens2, sourceFile);
1801
+ const inRangeCodegens = applicableCodegens.filter(
1802
+ (codegen2) => codegen2.range.pos <= textRange.pos && codegen2.range.end >= textRange.end
1803
+ );
1804
+ if (inRangeCodegens.length !== 1) {
1805
+ return yield* fail(new CodegenNotApplicableError("zero or multiple codegens in range"));
1806
+ }
1807
+ const { codegen, range } = inRangeCodegens[0];
1808
+ const edit = yield* codegen.apply(sourceFile, range);
1809
+ const updateHashComment = pipe(
1810
+ service(ChangeTracker),
1811
+ map3((changeTracker) => {
1812
+ changeTracker.deleteRange(sourceFile, range);
1813
+ changeTracker.insertText(sourceFile, range.pos, `${codegen.name}:${edit.hash}`);
1814
+ })
1815
+ );
1816
+ return {
1817
+ ...edit,
1818
+ apply: pipe(
1819
+ edit.apply,
1820
+ flatMap2(() => updateHashComment)
1821
+ ),
1822
+ ignore: updateHashComment
1823
+ };
1824
+ });
1443
1825
 
1444
1826
  // src/core/TypeCheckerApi.ts
1445
1827
  var TypeCheckerApi = Tag("TypeChecker");
1446
- var TypeCheckerApiCache = Tag("TypeCheckerApiCache");
1447
- function makeTypeCheckerApiCache() {
1448
- return {
1449
- expectedAndRealType: /* @__PURE__ */ new WeakMap()
1450
- };
1451
- }
1452
1828
  var deterministicTypeOrder = gen(function* () {
1453
1829
  const typeChecker = yield* service(TypeCheckerApi);
1454
1830
  return make((a, b) => {
@@ -1547,106 +1923,106 @@ var getInferredReturnType = fn("TypeCheckerApi.getInferredReturnType")(function*
1547
1923
  }
1548
1924
  return returnType;
1549
1925
  });
1550
- var expectedAndRealType = fn("TypeCheckerApi.expectedAndRealType")(function* (sourceFile) {
1551
- const cache = yield* service(TypeCheckerApiCache);
1552
- const resultCached = cache.expectedAndRealType.get(sourceFile);
1553
- if (resultCached) return resultCached;
1554
- const typeChecker = yield* service(TypeCheckerApi);
1555
- const ts = yield* service(TypeScriptApi);
1556
- const result = [];
1557
- const nodeToVisit = [sourceFile];
1558
- const appendNodeToVisit = (node) => {
1559
- nodeToVisit.push(node);
1560
- return void 0;
1561
- };
1562
- while (nodeToVisit.length > 0) {
1563
- const node = nodeToVisit.shift();
1564
- if (ts.isVariableDeclaration(node) && node.initializer) {
1565
- const expectedType = typeChecker.getTypeAtLocation(node.name);
1566
- const realType = typeChecker.getTypeAtLocation(node.initializer);
1567
- result.push([node.name, expectedType, node.initializer, realType]);
1568
- appendNodeToVisit(node.initializer);
1569
- continue;
1570
- } else if (ts.isCallExpression(node)) {
1571
- const resolvedSignature = typeChecker.getResolvedSignature(node);
1572
- if (resolvedSignature) {
1573
- resolvedSignature.getParameters().map((parameter, index) => {
1574
- const expectedType = typeChecker.getTypeOfSymbolAtLocation(parameter, node);
1575
- const realType = typeChecker.getTypeAtLocation(node.arguments[index]);
1576
- result.push([
1577
- node.arguments[index],
1578
- expectedType,
1579
- node.arguments[index],
1580
- realType
1581
- ]);
1582
- });
1583
- }
1584
- ts.forEachChild(node, appendNodeToVisit);
1585
- continue;
1586
- } else if (ts.isIdentifier(node) || ts.isStringLiteral(node) || ts.isNumericLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) {
1587
- const parent = node.parent;
1588
- if (ts.isObjectLiteralElement(parent)) {
1589
- if (ts.isObjectLiteralExpression(parent.parent) && parent.name === node) {
1590
- const type = typeChecker.getContextualType(parent.parent);
1591
- if (type) {
1592
- const symbol3 = typeChecker.getPropertyOfType(type, node.text);
1593
- if (symbol3) {
1594
- const expectedType = typeChecker.getTypeOfSymbolAtLocation(symbol3, node);
1595
- const realType = typeChecker.getTypeAtLocation(node);
1596
- result.push([node, expectedType, node, realType]);
1926
+ var expectedAndRealType = cachedBy(
1927
+ fn("TypeCheckerApi.expectedAndRealType")(function* (sourceFile) {
1928
+ const typeChecker = yield* service(TypeCheckerApi);
1929
+ const ts = yield* service(TypeScriptApi);
1930
+ const result = [];
1931
+ const nodeToVisit = [sourceFile];
1932
+ const appendNodeToVisit = (node) => {
1933
+ nodeToVisit.push(node);
1934
+ return void 0;
1935
+ };
1936
+ while (nodeToVisit.length > 0) {
1937
+ const node = nodeToVisit.shift();
1938
+ if (ts.isVariableDeclaration(node) && node.initializer) {
1939
+ const expectedType = typeChecker.getTypeAtLocation(node.name);
1940
+ const realType = typeChecker.getTypeAtLocation(node.initializer);
1941
+ result.push([node.name, expectedType, node.initializer, realType]);
1942
+ appendNodeToVisit(node.initializer);
1943
+ continue;
1944
+ } else if (ts.isCallExpression(node)) {
1945
+ const resolvedSignature = typeChecker.getResolvedSignature(node);
1946
+ if (resolvedSignature) {
1947
+ resolvedSignature.getParameters().map((parameter, index) => {
1948
+ const expectedType = typeChecker.getTypeOfSymbolAtLocation(parameter, node);
1949
+ const realType = typeChecker.getTypeAtLocation(node.arguments[index]);
1950
+ result.push([
1951
+ node.arguments[index],
1952
+ expectedType,
1953
+ node.arguments[index],
1954
+ realType
1955
+ ]);
1956
+ });
1957
+ }
1958
+ ts.forEachChild(node, appendNodeToVisit);
1959
+ continue;
1960
+ } else if (ts.isIdentifier(node) || ts.isStringLiteral(node) || ts.isNumericLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) {
1961
+ const parent = node.parent;
1962
+ if (ts.isObjectLiteralElement(parent)) {
1963
+ if (ts.isObjectLiteralExpression(parent.parent) && parent.name === node) {
1964
+ const type = typeChecker.getContextualType(parent.parent);
1965
+ if (type) {
1966
+ const symbol3 = typeChecker.getPropertyOfType(type, node.text);
1967
+ if (symbol3) {
1968
+ const expectedType = typeChecker.getTypeOfSymbolAtLocation(symbol3, node);
1969
+ const realType = typeChecker.getTypeAtLocation(node);
1970
+ result.push([node, expectedType, node, realType]);
1971
+ }
1597
1972
  }
1598
1973
  }
1599
1974
  }
1600
- }
1601
- ts.forEachChild(node, appendNodeToVisit);
1602
- continue;
1603
- } else if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
1604
- const expectedType = typeChecker.getTypeAtLocation(node.left);
1605
- const realType = typeChecker.getTypeAtLocation(node.right);
1606
- result.push([node.left, expectedType, node.right, realType]);
1607
- appendNodeToVisit(node.right);
1608
- continue;
1609
- } else if (ts.isReturnStatement(node) && node.expression) {
1610
- const parentDeclaration = yield* option(getAncestorConvertibleDeclaration(node));
1611
- if (isSome2(parentDeclaration)) {
1612
- const expectedType = yield* option(getInferredReturnType(parentDeclaration.value));
1613
- const realType = typeChecker.getTypeAtLocation(node.expression);
1975
+ ts.forEachChild(node, appendNodeToVisit);
1976
+ continue;
1977
+ } else if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
1978
+ const expectedType = typeChecker.getTypeAtLocation(node.left);
1979
+ const realType = typeChecker.getTypeAtLocation(node.right);
1980
+ result.push([node.left, expectedType, node.right, realType]);
1981
+ appendNodeToVisit(node.right);
1982
+ continue;
1983
+ } else if (ts.isReturnStatement(node) && node.expression) {
1984
+ const parentDeclaration = yield* option(getAncestorConvertibleDeclaration(node));
1985
+ if (isSome2(parentDeclaration)) {
1986
+ const expectedType = yield* option(getInferredReturnType(parentDeclaration.value));
1987
+ const realType = typeChecker.getTypeAtLocation(node.expression);
1988
+ if (isSome2(expectedType)) {
1989
+ result.push([node, expectedType.value, node, realType]);
1990
+ }
1991
+ }
1992
+ ts.forEachChild(node, appendNodeToVisit);
1993
+ continue;
1994
+ } else if (ts.isArrowFunction(node) && (node.typeParameters || []).length === 0 && ts.isExpression(node.body)) {
1995
+ const body = node.body;
1996
+ const expectedType = typeChecker.getContextualType(body);
1997
+ const realType = typeChecker.getTypeAtLocation(body);
1998
+ if (expectedType) {
1999
+ result.push([body, expectedType, body, realType]);
2000
+ }
2001
+ ts.forEachChild(body, appendNodeToVisit);
2002
+ continue;
2003
+ } else if (ts.isArrowFunction(node) && (node.typeParameters || []).length > 0 && ts.isExpression(node.body)) {
2004
+ const body = node.body;
2005
+ const expectedType = yield* option(getInferredReturnType(node));
2006
+ const realType = typeChecker.getTypeAtLocation(body);
1614
2007
  if (isSome2(expectedType)) {
1615
- result.push([node, expectedType.value, node, realType]);
2008
+ result.push([body, expectedType.value, body, realType]);
1616
2009
  }
2010
+ ts.forEachChild(body, appendNodeToVisit);
2011
+ continue;
2012
+ } else if (ts.isSatisfiesExpression(node)) {
2013
+ const expectedType = typeChecker.getTypeAtLocation(node.type);
2014
+ const realType = typeChecker.getTypeAtLocation(node.expression);
2015
+ result.push([node.expression, expectedType, node.expression, realType]);
2016
+ appendNodeToVisit(node.expression);
2017
+ continue;
1617
2018
  }
1618
2019
  ts.forEachChild(node, appendNodeToVisit);
1619
- continue;
1620
- } else if (ts.isArrowFunction(node) && (node.typeParameters || []).length === 0 && ts.isExpression(node.body)) {
1621
- const body = node.body;
1622
- const expectedType = typeChecker.getContextualType(body);
1623
- const realType = typeChecker.getTypeAtLocation(body);
1624
- if (expectedType) {
1625
- result.push([body, expectedType, body, realType]);
1626
- }
1627
- ts.forEachChild(body, appendNodeToVisit);
1628
- continue;
1629
- } else if (ts.isArrowFunction(node) && (node.typeParameters || []).length > 0 && ts.isExpression(node.body)) {
1630
- const body = node.body;
1631
- const expectedType = yield* option(getInferredReturnType(node));
1632
- const realType = typeChecker.getTypeAtLocation(body);
1633
- if (isSome2(expectedType)) {
1634
- result.push([body, expectedType.value, body, realType]);
1635
- }
1636
- ts.forEachChild(body, appendNodeToVisit);
1637
- continue;
1638
- } else if (ts.isSatisfiesExpression(node)) {
1639
- const expectedType = typeChecker.getTypeAtLocation(node.type);
1640
- const realType = typeChecker.getTypeAtLocation(node.expression);
1641
- result.push([node.expression, expectedType, node.expression, realType]);
1642
- appendNodeToVisit(node.expression);
1643
- continue;
1644
- }
1645
- ts.forEachChild(node, appendNodeToVisit);
1646
- }
1647
- cache.expectedAndRealType.set(sourceFile, result);
1648
- return result;
1649
- });
2020
+ }
2021
+ return result;
2022
+ }),
2023
+ "TypeCheckerApi.expectedAndRealType",
2024
+ (sourceFile) => sourceFile
2025
+ );
1650
2026
  var unrollUnionMembers = (type) => {
1651
2027
  const result = [];
1652
2028
  let toTest = [type];
@@ -1714,350 +2090,17 @@ function makeResolveExternalModuleName(typeChecker) {
1714
2090
  };
1715
2091
  }
1716
2092
 
1717
- // src/core/AST.ts
1718
- function collectSelfAndAncestorNodesInRange(node, textRange) {
1719
- return sync(() => {
1720
- let result = empty();
1721
- let parent = node;
1722
- while (parent) {
1723
- if (parent.end >= textRange.end) {
1724
- result = pipe(result, append(parent));
1725
- }
1726
- parent = parent.parent;
1727
- }
1728
- return result;
1729
- });
1730
- }
1731
- var getAncestorNodesInRange = fn("AST.getAncestorNodesInRange")(function* (sourceFile, textRange) {
1732
- const nodeAtPosition = yield* option(findNodeAtPosition(sourceFile, textRange.pos));
1733
- if (isNone2(nodeAtPosition)) return empty();
1734
- return yield* collectSelfAndAncestorNodesInRange(nodeAtPosition.value, textRange);
1735
- });
1736
- var NodeNotFoundError = class {
1737
- _tag = "@effect/language-service/NodeNotFoundError";
1738
- };
1739
- var findNodeAtPosition = fn("AST.findNodeAtPosition")(function* (sourceFile, position) {
1740
- const ts = yield* service(TypeScriptApi);
1741
- function find(node) {
1742
- if (position >= node.getStart() && position < node.getEnd()) {
1743
- return ts.forEachChild(node, find) || node;
1744
- }
1745
- return void 0;
1746
- }
1747
- const result = find(sourceFile);
1748
- if (!result) return yield* fail(new NodeNotFoundError());
1749
- return result;
1750
- });
1751
- var getCommentAtPosition = fn("TypeScriptApi.getCommentAtPosition")(function* (sourceFile, pos) {
1752
- const ts = yield* service(TypeScriptApi);
1753
- const token = yield* findNodeAtPosition(sourceFile, pos);
1754
- if (token === void 0 || token.kind === ts.SyntaxKind.JsxText || pos >= token.end - (ts.tokenToString(token.kind) || "").length) {
1755
- return yield* fail(new NodeNotFoundError());
1756
- }
1757
- const startPos = token.pos === 0 ? (ts.getShebang(sourceFile.text) || "").length : token.pos;
1758
- if (startPos === 0) return yield* fail(new NodeNotFoundError());
1759
- const result = ts.forEachTrailingCommentRange(sourceFile.text, startPos, isCommentInRange, pos) || ts.forEachLeadingCommentRange(sourceFile.text, startPos, isCommentInRange, pos);
1760
- if (!result) return yield* fail(new NodeNotFoundError());
1761
- return result;
1762
- });
1763
- function isCommentInRange(pos, end, kind, _nl, at) {
1764
- return at >= pos && at < end ? { pos, end, kind } : void 0;
1765
- }
1766
- var transformAsyncAwaitToEffectGen = fn("AST.transformAsyncAwaitToEffectGen")(
1767
- function* (node, effectModuleName, onAwait) {
1768
- const ts = yield* service(TypeScriptApi);
1769
- function visitor(_) {
1770
- if (ts.isAwaitExpression(_)) {
1771
- const expression = ts.visitEachChild(_.expression, visitor, ts.nullTransformationContext);
1772
- return ts.factory.createYieldExpression(
1773
- ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
1774
- onAwait(expression)
1775
- );
1776
- }
1777
- return ts.visitEachChild(_, visitor, ts.nullTransformationContext);
1778
- }
1779
- const generatorBody = visitor(node.body);
1780
- const effectGenCallExp = yield* createEffectGenCallExpression(effectModuleName, generatorBody);
1781
- let currentFlags = ts.getCombinedModifierFlags(node);
1782
- currentFlags &= ~ts.ModifierFlags.Async;
1783
- const newModifiers = ts.factory.createModifiersFromModifierFlags(currentFlags);
1784
- if (ts.isArrowFunction(node)) {
1785
- return ts.factory.createArrowFunction(
1786
- newModifiers,
1787
- node.typeParameters,
1788
- node.parameters,
1789
- void 0,
1790
- node.equalsGreaterThanToken,
1791
- effectGenCallExp
1792
- );
1793
- }
1794
- const newBody = ts.factory.createBlock([
1795
- ts.factory.createReturnStatement(effectGenCallExp)
1796
- ]);
1797
- if (ts.isFunctionDeclaration(node)) {
1798
- return ts.factory.createFunctionDeclaration(
1799
- newModifiers,
1800
- node.asteriskToken,
1801
- node.name,
1802
- node.typeParameters,
1803
- node.parameters,
1804
- void 0,
1805
- newBody
1806
- );
1807
- }
1808
- return ts.factory.createFunctionExpression(
1809
- newModifiers,
1810
- node.asteriskToken,
1811
- node.name,
1812
- node.typeParameters,
1813
- node.parameters,
1814
- void 0,
1815
- newBody
1816
- );
1817
- }
1818
- );
1819
- var addReturnTypeAnnotation = fn("AST.addReturnTypeAnnotation")(function* (sourceFile, declaration, typeNode) {
1820
- const ts = yield* service(TypeScriptApi);
1821
- const changes = yield* service(ChangeTracker);
1822
- const closeParen = ts.findChildOfKind(declaration, ts.SyntaxKind.CloseParenToken, sourceFile);
1823
- const needParens = ts.isArrowFunction(declaration) && closeParen === void 0;
1824
- const endNode = needParens ? declaration.parameters[0] : closeParen;
1825
- if (endNode) {
1826
- if (needParens) {
1827
- changes.insertNodeBefore(
1828
- sourceFile,
1829
- endNode,
1830
- ts.factory.createToken(ts.SyntaxKind.OpenParenToken)
1831
- );
1832
- changes.insertNodeAfter(
1833
- sourceFile,
1834
- endNode,
1835
- ts.factory.createToken(ts.SyntaxKind.CloseParenToken)
1836
- );
1837
- }
1838
- changes.insertNodeAt(sourceFile, endNode.end, typeNode, { prefix: ": " });
1839
- }
1840
- });
1841
- var removeReturnTypeAnnotation = fn("AST.removeReturnTypeAnnotation")(function* (sourceFile, declaration) {
1842
- const ts = yield* service(TypeScriptApi);
1843
- const changes = yield* service(ChangeTracker);
1844
- const closeParen = ts.findChildOfKind(declaration, ts.SyntaxKind.CloseParenToken, sourceFile);
1845
- const needParens = ts.isArrowFunction(declaration) && closeParen === void 0;
1846
- const endNode = needParens ? declaration.parameters[0] : closeParen;
1847
- if (endNode && declaration.type) {
1848
- changes.deleteRange(sourceFile, { pos: endNode.end, end: declaration.type.end });
1849
- }
1850
- });
1851
- var ImportModuleIdentifierNotFoundError = class {
1852
- _tag = "@effect/language-service/ImportModuleIdentifierNotFoundError";
1853
- };
1854
- var findImportedModuleIdentifier = fn("AST.findImportedModuleIdentifier")(
1855
- function* (sourceFile, test) {
1856
- const ts = yield* service(TypeScriptApi);
1857
- for (const statement of sourceFile.statements) {
1858
- if (!ts.isImportDeclaration(statement)) continue;
1859
- const importClause = statement.importClause;
1860
- if (!importClause) continue;
1861
- const namedBindings = importClause.namedBindings;
1862
- if (!namedBindings) continue;
1863
- if (ts.isNamespaceImport(namedBindings)) {
1864
- if (yield* test(namedBindings.name, statement.moduleSpecifier, none2())) {
1865
- return namedBindings.name;
1866
- }
1867
- } else if (ts.isNamedImports(namedBindings)) {
1868
- for (const importSpecifier of namedBindings.elements) {
1869
- const importProperty = fromNullable(importSpecifier.propertyName).pipe(
1870
- orElse(() => some2(importSpecifier.name))
1871
- );
1872
- if (yield* test(importSpecifier.name, statement.moduleSpecifier, importProperty)) {
1873
- return importSpecifier.name;
1874
- }
1875
- }
1876
- }
1877
- }
1878
- return yield* fail(new ImportModuleIdentifierNotFoundError());
1879
- }
1880
- );
1881
- function findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, packageName, moduleName) {
1882
- return findImportedModuleIdentifier(
1883
- sourceFile,
1884
- fn(
1885
- "AST.findImportedModuleIdentifierByPackageAndNameOrBarrel.findImportedModuleIdentifier"
1886
- )(function* (_, fromModule, importProperty) {
1887
- const ts = yield* service(TypeScriptApi);
1888
- if (isNone2(importProperty) && ts.isStringLiteral(fromModule) && fromModule.text === packageName + "/" + moduleName) {
1889
- return true;
1890
- }
1891
- if (isSome2(importProperty) && ts.isIdentifier(importProperty.value) && importProperty.value.text === moduleName && ts.isStringLiteral(fromModule) && fromModule.text === packageName) {
1892
- return true;
1893
- }
1894
- return false;
1895
- })
1896
- );
1897
- }
1898
- var simplifyTypeNode = fn("AST.simplifyTypeNode")(function* (typeNode) {
1899
- const ts = yield* service(TypeScriptApi);
1900
- function collectCallable(typeNode2) {
1901
- if (ts.isParenthesizedTypeNode(typeNode2)) return collectCallable(typeNode2.type);
1902
- if (ts.isFunctionTypeNode(typeNode2)) {
1903
- return some2([
1904
- ts.factory.createCallSignature(typeNode2.typeParameters, typeNode2.parameters, typeNode2.type)
1905
- ]);
1906
- }
1907
- if (ts.isTypeLiteralNode(typeNode2)) {
1908
- const allCallSignatures = typeNode2.members.every(ts.isCallSignatureDeclaration);
1909
- if (allCallSignatures) {
1910
- return some2(typeNode2.members);
1911
- }
1912
- }
1913
- if (ts.isIntersectionTypeNode(typeNode2)) {
1914
- const members = typeNode2.types.map((node) => collectCallable(node));
1915
- if (members.every(isSome2)) {
1916
- return some2(members.map((_) => isSome2(_) ? _.value : []).flat());
1917
- }
1918
- }
1919
- return none2();
1920
- }
1921
- const callSignatures = collectCallable(typeNode);
1922
- if (isSome2(callSignatures) && callSignatures.value.length > 1) {
1923
- return ts.factory.createTypeLiteralNode(callSignatures.value);
1924
- }
1925
- return typeNode;
1926
- });
1927
- var tryPreserveDeclarationSemantics = fn("AST.tryPreserveDeclarationSemantics")(
1928
- function* (nodeToReplace, node) {
1929
- const ts = yield* service(TypeScriptApi);
1930
- if (!ts.isExpression(node)) return node;
1931
- if (ts.isFunctionDeclaration(nodeToReplace)) {
1932
- if (!nodeToReplace.name) return node;
1933
- return ts.factory.createVariableStatement(
1934
- nodeToReplace.modifiers,
1935
- ts.factory.createVariableDeclarationList(
1936
- [ts.factory.createVariableDeclaration(
1937
- nodeToReplace.name,
1938
- void 0,
1939
- void 0,
1940
- node
1941
- )],
1942
- ts.NodeFlags.Const
1943
- )
1944
- );
1945
- } else if (ts.isMethodDeclaration(nodeToReplace)) {
1946
- return ts.factory.createPropertyDeclaration(
1947
- nodeToReplace.modifiers,
1948
- nodeToReplace.name,
1949
- void 0,
1950
- void 0,
1951
- node
1952
- );
1953
- }
1954
- return node;
1955
- }
1956
- );
1957
- var parseAccessedExpressionForCompletion = fn(
1958
- "AST.parseAccessedExpressionForCompletion"
1959
- )(
1960
- function* (sourceFile, position) {
1961
- const ts = yield* service(TypeScriptApi);
1962
- const precedingToken = ts.findPrecedingToken(position, sourceFile, void 0, true);
1963
- if (!precedingToken) return yield* fail(new NodeNotFoundError());
1964
- let accessedObject = precedingToken;
1965
- let replacementSpan = ts.createTextSpan(position, 0);
1966
- let outerNode = precedingToken;
1967
- if (ts.isIdentifier(precedingToken) && precedingToken.parent && ts.isPropertyAccessExpression(precedingToken.parent)) {
1968
- replacementSpan = ts.createTextSpan(
1969
- precedingToken.parent.getStart(sourceFile),
1970
- precedingToken.end - precedingToken.parent.getStart(sourceFile)
1971
- );
1972
- accessedObject = precedingToken.parent.expression;
1973
- outerNode = precedingToken.parent;
1974
- } else if (ts.isToken(precedingToken) && precedingToken.kind === ts.SyntaxKind.DotToken && ts.isPropertyAccessExpression(precedingToken.parent)) {
1975
- replacementSpan = ts.createTextSpan(
1976
- precedingToken.parent.getStart(sourceFile),
1977
- precedingToken.end - precedingToken.parent.getStart(sourceFile)
1978
- );
1979
- accessedObject = precedingToken.parent.expression;
1980
- outerNode = precedingToken.parent;
1981
- } else if (ts.isIdentifier(precedingToken) && precedingToken.parent) {
1982
- replacementSpan = ts.createTextSpan(
1983
- precedingToken.getStart(sourceFile),
1984
- precedingToken.end - precedingToken.getStart(sourceFile)
1985
- );
1986
- accessedObject = precedingToken;
1987
- outerNode = precedingToken;
1988
- } else {
1989
- return yield* fail(new NodeNotFoundError());
1990
- }
1991
- return { accessedObject, outerNode, replacementSpan };
1992
- }
1993
- );
1994
- var parseDataForExtendsClassCompletion = fn(
1995
- "AST.parseDataForExtendsClassCompletion"
1996
- )(function* (sourceFile, position) {
1997
- const ts = yield* service(TypeScriptApi);
1998
- const { accessedObject, outerNode, replacementSpan } = yield* parseAccessedExpressionForCompletion(
1999
- sourceFile,
2000
- position
2001
- );
2002
- if (!ts.isIdentifier(accessedObject)) return yield* fail(new NodeNotFoundError());
2003
- let classDeclaration = outerNode.parent;
2004
- while (ts.isExpressionWithTypeArguments(classDeclaration) || ts.isHeritageClause(classDeclaration)) {
2005
- if (!classDeclaration.parent) break;
2006
- classDeclaration = classDeclaration.parent;
2007
- }
2008
- if (!ts.isClassDeclaration(classDeclaration)) return yield* fail(new NodeNotFoundError());
2009
- if (!classDeclaration.name) return yield* fail(new NodeNotFoundError());
2010
- return {
2011
- accessedObject,
2012
- classDeclaration,
2013
- className: classDeclaration.name,
2014
- replacementSpan
2015
- };
2016
- });
2017
- var createEffectGenCallExpression = fn("AST.createEffectGenCallExpression")(function* (effectModuleIdentifierName, node) {
2018
- const ts = yield* service(TypeScriptApi);
2019
- const generator = ts.factory.createFunctionExpression(
2020
- void 0,
2021
- ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
2022
- void 0,
2023
- [],
2024
- [],
2025
- void 0,
2026
- node
2027
- // NOTE(mattia): intended, to use same routine for both ConciseBody and Body
2028
- );
2029
- return ts.factory.createCallExpression(
2030
- ts.factory.createPropertyAccessExpression(
2031
- ts.factory.createIdentifier(effectModuleIdentifierName),
2032
- "gen"
2033
- ),
2034
- void 0,
2035
- [generator]
2036
- );
2037
- });
2038
- var createEffectGenCallExpressionWithBlock = fn(
2039
- "AST.createEffectGenCallExpressionWithBlock"
2040
- )(function* (effectModuleIdentifierName, statement) {
2093
+ // src/core/TypeParser.ts
2094
+ var TypeParser = Tag("@effect/language-service/TypeParser");
2095
+ var nanoLayer2 = (fa) => gen(function* () {
2041
2096
  const ts = yield* service(TypeScriptApi);
2042
- return yield* createEffectGenCallExpression(
2043
- effectModuleIdentifierName,
2044
- ts.factory.createBlock(Array.isArray(statement) ? statement : [statement], false)
2097
+ const tsUtils = yield* service(TypeScriptUtils);
2098
+ const typeChecker = yield* service(TypeCheckerApi);
2099
+ return yield* pipe(
2100
+ fa,
2101
+ provideService(TypeParser, make2(ts, tsUtils, typeChecker))
2045
2102
  );
2046
2103
  });
2047
- var createReturnYieldStarStatement = fn("AST.createReturnYieldStarStatement")(
2048
- function* (expr) {
2049
- const ts = yield* service(TypeScriptApi);
2050
- return ts.factory.createReturnStatement(
2051
- ts.factory.createYieldExpression(
2052
- ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
2053
- expr
2054
- )
2055
- );
2056
- }
2057
- );
2058
-
2059
- // src/core/TypeParser.ts
2060
- var TypeParser = Tag("@effect/language-service/TypeParser");
2061
2104
  var TypeParserIssue = class _TypeParserIssue {
2062
2105
  _tag = "@effect/language-service/TypeParserIssue";
2063
2106
  static issue = fail(new _TypeParserIssue());
@@ -2065,7 +2108,7 @@ var TypeParserIssue = class _TypeParserIssue {
2065
2108
  function typeParserIssue(_message, _type, _node) {
2066
2109
  return TypeParserIssue.issue;
2067
2110
  }
2068
- function make2(ts, typeChecker) {
2111
+ function make2(ts, tsUtils, typeChecker) {
2069
2112
  function covariantTypeArgument(type) {
2070
2113
  const signatures = type.getCallSignatures();
2071
2114
  if (signatures.length !== 1) {
@@ -2223,6 +2266,36 @@ function make2(ts, typeChecker) {
2223
2266
  "TypeParser.effectSubtype",
2224
2267
  (type) => type
2225
2268
  );
2269
+ const importedSchemaModule = cachedBy(
2270
+ fn("TypeParser.importedSchemaModule")(function* (node) {
2271
+ const type = typeChecker.getTypeAtLocation(node);
2272
+ const propertySymbol = typeChecker.getPropertyOfType(type, "Class");
2273
+ if (!propertySymbol) {
2274
+ return yield* typeParserIssue("Type has no 'Class' property", type, node);
2275
+ }
2276
+ if (!ts.isExpression(node)) {
2277
+ return yield* typeParserIssue("Node is not an expression", type, node);
2278
+ }
2279
+ return node;
2280
+ }),
2281
+ "TypeParser.importedSchemaModule",
2282
+ (node) => node
2283
+ );
2284
+ const importedContextModule = cachedBy(
2285
+ fn("TypeParser.importedContextModule")(function* (node) {
2286
+ const type = typeChecker.getTypeAtLocation(node);
2287
+ const propertySymbol = typeChecker.getPropertyOfType(type, "Tag");
2288
+ if (!propertySymbol) {
2289
+ return yield* typeParserIssue("Type has no 'Tag' property", type, node);
2290
+ }
2291
+ if (!ts.isExpression(node)) {
2292
+ return yield* typeParserIssue("Node is not an expression", type, node);
2293
+ }
2294
+ return node;
2295
+ }),
2296
+ "TypeParser.importedContextModule",
2297
+ (node) => node
2298
+ );
2226
2299
  const importedEffectModule = cachedBy(
2227
2300
  fn("TypeParser.importedEffectModule")(function* (node) {
2228
2301
  const type = typeChecker.getTypeAtLocation(node);
@@ -2407,15 +2480,11 @@ function make2(ts, typeChecker) {
2407
2480
  if (!explicitReturn && !(successType.flags & ts.TypeFlags.VoidLike)) {
2408
2481
  replacementNode = pipe(
2409
2482
  gen(function* () {
2410
- const effectIdentifier = pipe(
2411
- yield* option(
2412
- findImportedModuleIdentifierByPackageAndNameOrBarrel(node.getSourceFile(), "effect", "Effect")
2413
- ),
2414
- match({
2415
- onNone: () => "Effect",
2416
- onSome: (_) => _.text
2417
- })
2418
- );
2483
+ const effectIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
2484
+ node.getSourceFile(),
2485
+ "effect",
2486
+ "Effect"
2487
+ ) || "Effect";
2419
2488
  return ts.factory.createCallExpression(
2420
2489
  ts.factory.createPropertyAccessExpression(
2421
2490
  ts.factory.createIdentifier(effectIdentifier),
@@ -2583,6 +2652,284 @@ function make2(ts, typeChecker) {
2583
2652
  "TypeParser.promiseLike",
2584
2653
  (type) => type
2585
2654
  );
2655
+ const extendsSchemaClass = cachedBy(
2656
+ fn("TypeParser.extendsSchemaClass")(function* (atLocation) {
2657
+ if (!atLocation.name) {
2658
+ return yield* typeParserIssue("Class has no name", void 0, atLocation);
2659
+ }
2660
+ const heritageClauses = atLocation.heritageClauses;
2661
+ if (!heritageClauses) {
2662
+ return yield* typeParserIssue("Class has no heritage clauses", void 0, atLocation);
2663
+ }
2664
+ for (const heritageClause of heritageClauses) {
2665
+ for (const typeX of heritageClause.types) {
2666
+ if (ts.isExpressionWithTypeArguments(typeX)) {
2667
+ const expression = typeX.expression;
2668
+ if (ts.isCallExpression(expression)) {
2669
+ const schemaCall = expression.expression;
2670
+ if (ts.isCallExpression(schemaCall) && schemaCall.typeArguments && schemaCall.typeArguments.length > 0) {
2671
+ const selfTypeNode = schemaCall.typeArguments[0];
2672
+ const schemaIdentifier = schemaCall.expression;
2673
+ if (ts.isPropertyAccessExpression(schemaIdentifier) && ts.isIdentifier(schemaIdentifier.name) && schemaIdentifier.name.text === "Class") {
2674
+ const parsedSchemaModule = yield* pipe(
2675
+ importedSchemaModule(schemaIdentifier.expression),
2676
+ option
2677
+ );
2678
+ if (isSome2(parsedSchemaModule)) {
2679
+ return {
2680
+ className: atLocation.name,
2681
+ selfTypeNode,
2682
+ Schema: parsedSchemaModule.value
2683
+ };
2684
+ }
2685
+ }
2686
+ }
2687
+ }
2688
+ }
2689
+ }
2690
+ }
2691
+ return yield* typeParserIssue("Class does not extend Schema.Class", void 0, atLocation);
2692
+ }),
2693
+ "TypeParser.extendsSchemaClass",
2694
+ (atLocation) => atLocation
2695
+ );
2696
+ const extendsSchemaTaggedClass = cachedBy(
2697
+ fn("TypeParser.extendsSchemaTaggedClass")(function* (atLocation) {
2698
+ if (!atLocation.name) {
2699
+ return yield* typeParserIssue("Class has no name", void 0, atLocation);
2700
+ }
2701
+ const heritageClauses = atLocation.heritageClauses;
2702
+ if (!heritageClauses) {
2703
+ return yield* typeParserIssue("Class has no heritage clauses", void 0, atLocation);
2704
+ }
2705
+ for (const heritageClause of heritageClauses) {
2706
+ for (const typeX of heritageClause.types) {
2707
+ if (ts.isExpressionWithTypeArguments(typeX)) {
2708
+ const expression = typeX.expression;
2709
+ if (ts.isCallExpression(expression)) {
2710
+ const tagCall = expression.expression;
2711
+ if (ts.isCallExpression(tagCall)) {
2712
+ const schemaCall = tagCall.expression;
2713
+ if (ts.isCallExpression(schemaCall) && schemaCall.typeArguments && schemaCall.typeArguments.length > 0) {
2714
+ const selfTypeNode = schemaCall.typeArguments[0];
2715
+ const schemaIdentifier = schemaCall.expression;
2716
+ if (ts.isPropertyAccessExpression(schemaIdentifier) && ts.isIdentifier(schemaIdentifier.name) && schemaIdentifier.name.text === "TaggedClass") {
2717
+ const parsedSchemaModule = yield* pipe(
2718
+ importedSchemaModule(schemaIdentifier.expression),
2719
+ option
2720
+ );
2721
+ if (isSome2(parsedSchemaModule)) {
2722
+ return {
2723
+ className: atLocation.name,
2724
+ selfTypeNode,
2725
+ Schema: parsedSchemaModule.value
2726
+ };
2727
+ }
2728
+ }
2729
+ }
2730
+ }
2731
+ }
2732
+ }
2733
+ }
2734
+ }
2735
+ return yield* typeParserIssue("Class does not extend Schema.TaggedClass", void 0, atLocation);
2736
+ }),
2737
+ "TypeParser.extendsSchemaTaggedClass",
2738
+ (atLocation) => atLocation
2739
+ );
2740
+ const extendsSchemaTaggedError = cachedBy(
2741
+ fn("TypeParser.extendsSchemaTaggedError")(function* (atLocation) {
2742
+ if (!atLocation.name) {
2743
+ return yield* typeParserIssue("Class has no name", void 0, atLocation);
2744
+ }
2745
+ const heritageClauses = atLocation.heritageClauses;
2746
+ if (!heritageClauses) {
2747
+ return yield* typeParserIssue("Class has no heritage clauses", void 0, atLocation);
2748
+ }
2749
+ for (const heritageClause of heritageClauses) {
2750
+ for (const typeX of heritageClause.types) {
2751
+ if (ts.isExpressionWithTypeArguments(typeX)) {
2752
+ const expression = typeX.expression;
2753
+ if (ts.isCallExpression(expression)) {
2754
+ const tagCall = expression.expression;
2755
+ if (ts.isCallExpression(tagCall)) {
2756
+ const schemaCall = tagCall.expression;
2757
+ if (ts.isCallExpression(schemaCall) && schemaCall.typeArguments && schemaCall.typeArguments.length > 0) {
2758
+ const selfTypeNode = schemaCall.typeArguments[0];
2759
+ const schemaIdentifier = schemaCall.expression;
2760
+ if (ts.isPropertyAccessExpression(schemaIdentifier) && ts.isIdentifier(schemaIdentifier.name) && schemaIdentifier.name.text === "TaggedError") {
2761
+ const parsedSchemaModule = yield* pipe(
2762
+ importedSchemaModule(schemaIdentifier.expression),
2763
+ option
2764
+ );
2765
+ if (isSome2(parsedSchemaModule)) {
2766
+ return {
2767
+ className: atLocation.name,
2768
+ selfTypeNode,
2769
+ Schema: parsedSchemaModule.value
2770
+ };
2771
+ }
2772
+ }
2773
+ }
2774
+ }
2775
+ }
2776
+ }
2777
+ }
2778
+ }
2779
+ return yield* typeParserIssue("Class does not extend Schema.TaggedError", void 0, atLocation);
2780
+ }),
2781
+ "TypeParser.extendsSchemaTaggedError",
2782
+ (atLocation) => atLocation
2783
+ );
2784
+ const extendsSchemaTaggedRequest = cachedBy(
2785
+ fn("TypeParser.extendsSchemaTaggedRequest")(function* (atLocation) {
2786
+ if (!atLocation.name) {
2787
+ return yield* typeParserIssue("Class has no name", void 0, atLocation);
2788
+ }
2789
+ const heritageClauses = atLocation.heritageClauses;
2790
+ if (!heritageClauses) {
2791
+ return yield* typeParserIssue("Class has no heritage clauses", void 0, atLocation);
2792
+ }
2793
+ for (const heritageClause of heritageClauses) {
2794
+ for (const typeX of heritageClause.types) {
2795
+ if (ts.isExpressionWithTypeArguments(typeX)) {
2796
+ const expression = typeX.expression;
2797
+ if (ts.isCallExpression(expression)) {
2798
+ const tagCall = expression.expression;
2799
+ if (ts.isCallExpression(tagCall)) {
2800
+ const schemaCall = tagCall.expression;
2801
+ if (ts.isCallExpression(schemaCall) && schemaCall.typeArguments && schemaCall.typeArguments.length > 0) {
2802
+ const selfTypeNode = schemaCall.typeArguments[0];
2803
+ const schemaIdentifier = schemaCall.expression;
2804
+ if (ts.isPropertyAccessExpression(schemaIdentifier) && ts.isIdentifier(schemaIdentifier.name) && schemaIdentifier.name.text === "TaggedRequest") {
2805
+ const parsedSchemaModule = yield* pipe(
2806
+ importedSchemaModule(schemaIdentifier.expression),
2807
+ option
2808
+ );
2809
+ if (isSome2(parsedSchemaModule)) {
2810
+ return {
2811
+ className: atLocation.name,
2812
+ selfTypeNode,
2813
+ Schema: parsedSchemaModule.value
2814
+ };
2815
+ }
2816
+ }
2817
+ }
2818
+ }
2819
+ }
2820
+ }
2821
+ }
2822
+ }
2823
+ return yield* typeParserIssue("Class does not extend Schema.TaggedRequest", void 0, atLocation);
2824
+ }),
2825
+ "TypeParser.extendsSchemaTaggedRequest",
2826
+ (atLocation) => atLocation
2827
+ );
2828
+ const extendsContextTag = cachedBy(
2829
+ fn("TypeParser.extendsContextTag")(function* (atLocation) {
2830
+ if (!atLocation.name) {
2831
+ return yield* typeParserIssue("Class has no name", void 0, atLocation);
2832
+ }
2833
+ const classSym = typeChecker.getSymbolAtLocation(atLocation.name);
2834
+ if (!classSym) return yield* typeParserIssue("Class has no symbol", void 0, atLocation);
2835
+ const type = typeChecker.getTypeOfSymbol(classSym);
2836
+ const heritageClauses = atLocation.heritageClauses;
2837
+ if (!heritageClauses) {
2838
+ return yield* typeParserIssue("Class has no heritage clauses", void 0, atLocation);
2839
+ }
2840
+ for (const heritageClause of heritageClauses) {
2841
+ for (const typeX of heritageClause.types) {
2842
+ if (ts.isExpressionWithTypeArguments(typeX)) {
2843
+ const wholeCall = typeX.expression;
2844
+ if (ts.isCallExpression(wholeCall)) {
2845
+ const contextTagCall = wholeCall.expression;
2846
+ if (ts.isCallExpression(contextTagCall) && wholeCall.typeArguments && wholeCall.typeArguments.length > 0) {
2847
+ const contextTagIdentifier = contextTagCall.expression;
2848
+ const selfTypeNode = wholeCall.typeArguments[0];
2849
+ if (ts.isPropertyAccessExpression(contextTagIdentifier) && ts.isIdentifier(contextTagIdentifier.name) && contextTagIdentifier.name.text === "Tag") {
2850
+ const parsedContextModule = yield* pipe(
2851
+ importedContextModule(contextTagIdentifier.expression),
2852
+ option
2853
+ );
2854
+ if (isSome2(parsedContextModule)) {
2855
+ const tagType = yield* contextTag(type, atLocation);
2856
+ return {
2857
+ className: atLocation.name,
2858
+ selfTypeNode,
2859
+ args: contextTagCall.arguments,
2860
+ Identifier: tagType.Identifier,
2861
+ Tag: parsedContextModule.value
2862
+ };
2863
+ }
2864
+ }
2865
+ }
2866
+ }
2867
+ }
2868
+ }
2869
+ }
2870
+ return yield* typeParserIssue("Class does not extend Context.Tag", void 0, atLocation);
2871
+ }),
2872
+ "TypeParser.extendsContextTag",
2873
+ (atLocation) => atLocation
2874
+ );
2875
+ const extendsEffectService = cachedBy(
2876
+ fn("TypeParser.extendsEffectService")(function* (atLocation) {
2877
+ if (!atLocation.name) {
2878
+ return yield* typeParserIssue("Class has no name", void 0, atLocation);
2879
+ }
2880
+ const classSym = typeChecker.getSymbolAtLocation(atLocation.name);
2881
+ if (!classSym) return yield* typeParserIssue("Class has no symbol", void 0, atLocation);
2882
+ const type = typeChecker.getTypeOfSymbol(classSym);
2883
+ const heritageClauses = atLocation.heritageClauses;
2884
+ if (!heritageClauses) {
2885
+ return yield* typeParserIssue("Class has no heritage clauses", void 0, atLocation);
2886
+ }
2887
+ for (const heritageClause of heritageClauses) {
2888
+ for (const typeX of heritageClause.types) {
2889
+ if (ts.isExpressionWithTypeArguments(typeX)) {
2890
+ const wholeCall = typeX.expression;
2891
+ if (ts.isCallExpression(wholeCall)) {
2892
+ const effectServiceCall = wholeCall.expression;
2893
+ if (ts.isCallExpression(effectServiceCall) && effectServiceCall.typeArguments && effectServiceCall.typeArguments.length > 0) {
2894
+ const effectServiceIdentifier = effectServiceCall.expression;
2895
+ const selfTypeNode = effectServiceCall.typeArguments[0];
2896
+ if (ts.isPropertyAccessExpression(effectServiceIdentifier) && ts.isIdentifier(effectServiceIdentifier.name) && effectServiceIdentifier.name.text === "Service") {
2897
+ const parsedContextTag = yield* pipe(
2898
+ importedEffectModule(effectServiceIdentifier.expression),
2899
+ flatMap2(() => contextTag(type, atLocation)),
2900
+ option
2901
+ );
2902
+ if (isSome2(parsedContextTag)) {
2903
+ let accessors2 = void 0;
2904
+ if (wholeCall.arguments.length >= 2) {
2905
+ const args2 = wholeCall.arguments[1];
2906
+ if (ts.isObjectLiteralExpression(args2)) {
2907
+ for (const property of args2.properties) {
2908
+ if (ts.isPropertyAssignment(property) && property.name && ts.isIdentifier(property.name) && property.name.text === "accessors" && property.initializer && property.initializer.kind === ts.SyntaxKind.TrueKeyword) {
2909
+ accessors2 = true;
2910
+ }
2911
+ }
2912
+ }
2913
+ }
2914
+ return {
2915
+ ...parsedContextTag.value,
2916
+ className: atLocation.name,
2917
+ selfTypeNode,
2918
+ args: wholeCall.arguments,
2919
+ accessors: accessors2
2920
+ };
2921
+ }
2922
+ }
2923
+ }
2924
+ }
2925
+ }
2926
+ }
2927
+ }
2928
+ return yield* typeParserIssue("Class does not extend Effect.Service", void 0, atLocation);
2929
+ }),
2930
+ "TypeParser.extendsEffectService",
2931
+ (atLocation) => atLocation
2932
+ );
2586
2933
  return {
2587
2934
  effectType,
2588
2935
  strictEffectType,
@@ -2599,10 +2946,79 @@ function make2(ts, typeChecker) {
2599
2946
  pipeableType,
2600
2947
  pipeCall,
2601
2948
  scopeType,
2602
- promiseLike
2949
+ promiseLike,
2950
+ extendsEffectService,
2951
+ extendsContextTag,
2952
+ extendsSchemaClass,
2953
+ extendsSchemaTaggedClass,
2954
+ extendsSchemaTaggedError,
2955
+ extendsSchemaTaggedRequest
2603
2956
  };
2604
2957
  }
2605
2958
 
2959
+ // src/diagnostics/classSelfMismatch.ts
2960
+ var classSelfMismatch = createDiagnostic({
2961
+ name: "classSelfMismatch",
2962
+ code: 20,
2963
+ severity: "error",
2964
+ apply: fn("classSelfMismatch.apply")(function* (sourceFile, report) {
2965
+ const ts = yield* service(TypeScriptApi);
2966
+ const typeParser = yield* service(TypeParser);
2967
+ const nodeToVisit = [];
2968
+ const appendNodeToVisit = (node) => {
2969
+ nodeToVisit.push(node);
2970
+ return void 0;
2971
+ };
2972
+ ts.forEachChild(sourceFile, appendNodeToVisit);
2973
+ while (nodeToVisit.length > 0) {
2974
+ const node = nodeToVisit.shift();
2975
+ if (ts.isClassDeclaration(node) && node.name && node.heritageClauses) {
2976
+ const result = yield* pipe(
2977
+ typeParser.extendsEffectService(node),
2978
+ orElse2(() => typeParser.extendsContextTag(node)),
2979
+ orElse2(() => typeParser.extendsSchemaClass(node)),
2980
+ orElse2(() => typeParser.extendsSchemaTaggedClass(node)),
2981
+ orElse2(() => typeParser.extendsSchemaTaggedError(node)),
2982
+ orElse2(() => typeParser.extendsSchemaTaggedRequest(node)),
2983
+ orElse2(() => void_)
2984
+ );
2985
+ if (result) {
2986
+ const { className, selfTypeNode } = result;
2987
+ let actualName = "";
2988
+ if (ts.isTypeReferenceNode(selfTypeNode)) {
2989
+ if (ts.isIdentifier(selfTypeNode.typeName)) {
2990
+ actualName = selfTypeNode.typeName.text;
2991
+ } else if (ts.isQualifiedName(selfTypeNode.typeName)) {
2992
+ actualName = selfTypeNode.typeName.right.text;
2993
+ }
2994
+ }
2995
+ const expectedName = className.text;
2996
+ if (actualName !== expectedName) {
2997
+ report({
2998
+ location: selfTypeNode,
2999
+ messageText: `Self type parameter should be '${expectedName}'`,
3000
+ fixes: [{
3001
+ fixName: "classSelfMismatch_fix",
3002
+ description: `Replace '${actualName}' with '${expectedName}'`,
3003
+ apply: gen(function* () {
3004
+ const changeTracker = yield* service(ChangeTracker);
3005
+ const typeArgs = ts.isTypeReferenceNode(selfTypeNode) ? selfTypeNode.typeArguments : void 0;
3006
+ const newTypeReference = ts.factory.createTypeReferenceNode(
3007
+ ts.factory.createIdentifier(expectedName),
3008
+ typeArgs
3009
+ );
3010
+ changeTracker.replaceNode(sourceFile, selfTypeNode, newTypeReference);
3011
+ })
3012
+ }]
3013
+ });
3014
+ }
3015
+ }
3016
+ }
3017
+ ts.forEachChild(node, appendNodeToVisit);
3018
+ }
3019
+ })
3020
+ });
3021
+
2606
3022
  // src/diagnostics/duplicatePackage.ts
2607
3023
  var checkedPackagesCache = /* @__PURE__ */ new Map();
2608
3024
  var programResolvedCacheSize = /* @__PURE__ */ new Map();
@@ -2612,6 +3028,7 @@ var duplicatePackage = createDiagnostic({
2612
3028
  severity: "warning",
2613
3029
  apply: fn("duplicatePackage.apply")(function* (sourceFile, report) {
2614
3030
  const program = yield* service(TypeScriptProgram);
3031
+ const tsUtils = yield* service(TypeScriptUtils);
2615
3032
  const options = yield* service(LanguageServicePluginOptions);
2616
3033
  if (sourceFile.statements.length < 1) return;
2617
3034
  let resolvedPackages = checkedPackagesCache.get(sourceFile.fileName) || {};
@@ -2621,7 +3038,7 @@ var duplicatePackage = createDiagnostic({
2621
3038
  const seenPackages = /* @__PURE__ */ new Set();
2622
3039
  resolvedPackages = {};
2623
3040
  program.getSourceFiles().map((_) => {
2624
- const packageInfo = parsePackageContentNameAndVersionFromScope(_);
3041
+ const packageInfo = tsUtils.parsePackageContentNameAndVersionFromScope(_);
2625
3042
  if (!packageInfo) return;
2626
3043
  const packageNameAndVersion = packageInfo.name + "@" + packageInfo.version;
2627
3044
  if (seenPackages.has(packageNameAndVersion)) return;
@@ -2638,7 +3055,7 @@ var duplicatePackage = createDiagnostic({
2638
3055
  if (Object.keys(resolvedPackages[packageName]).length > 1) {
2639
3056
  const versions = Object.keys(resolvedPackages[packageName]);
2640
3057
  report({
2641
- node: sourceFile.statements[0],
3058
+ location: sourceFile.statements[0],
2642
3059
  messageText: `Package ${packageName} is referenced multiple times with different versions (${versions.join(", ")}) and may cause unexpected type errors.
2643
3060
  Cleanup your dependencies and your package lockfile to avoid multiple instances of this package and reload the project.
2644
3061
  If this is intended set the LSP config "allowedDuplicatedPackages" to ${JSON.stringify(options.allowedDuplicatedPackages.concat([packageName]))}.
@@ -2685,7 +3102,7 @@ var effectInVoidSuccess = createDiagnostic({
2685
3102
  map3(({ voidedEffect }) => {
2686
3103
  report(
2687
3104
  {
2688
- node,
3105
+ location: node,
2689
3106
  messageText: `There is a nested '${typeChecker.typeToString(voidedEffect)}' in the 'void' success channel, beware that this could lead to nested Effect<Effect<...>> that won't be executed.`,
2690
3107
  fixes: []
2691
3108
  }
@@ -2734,7 +3151,7 @@ var floatingEffect = createDiagnostic({
2734
3151
  );
2735
3152
  if (isNone2(allowedFloatingEffects)) {
2736
3153
  report({
2737
- node,
3154
+ location: node,
2738
3155
  messageText: `Effect must be yielded or assigned to a variable.`,
2739
3156
  fixes: []
2740
3157
  });
@@ -2777,7 +3194,7 @@ var genericEffectServices = createDiagnostic({
2777
3194
  typeParser.contextTag(type, node),
2778
3195
  map3(() => {
2779
3196
  report({
2780
- node: reportAt,
3197
+ location: reportAt,
2781
3198
  messageText: `Effect Services with type parameters are not supported because they cannot be properly discriminated at runtime, which may cause unexpected behavior.`,
2782
3199
  fixes: []
2783
3200
  });
@@ -2799,17 +3216,16 @@ var importFromBarrel = createDiagnostic({
2799
3216
  const languageServicePluginOptions = yield* service(LanguageServicePluginOptions);
2800
3217
  if (languageServicePluginOptions.namespaceImportPackages.length === 0) return;
2801
3218
  const ts = yield* service(TypeScriptApi);
3219
+ const tsUtils = yield* service(TypeScriptUtils);
2802
3220
  const typeChecker = yield* service(TypeCheckerApi);
2803
3221
  const program = yield* service(TypeScriptProgram);
2804
3222
  const packageNamesToCheck = flatten(
2805
- yield* all(
2806
- ...languageServicePluginOptions.namespaceImportPackages.map(
2807
- (packageName) => resolveModulePattern(sourceFile, packageName)
2808
- )
3223
+ languageServicePluginOptions.namespaceImportPackages.map(
3224
+ (packageName) => tsUtils.resolveModulePattern(sourceFile, packageName)
2809
3225
  )
2810
3226
  );
2811
3227
  const isImportedFromBarrelExport = (element) => {
2812
- const getModuleSpecifier = makeGetModuleSpecifier(ts);
3228
+ const getModuleSpecifier = tsUtils.makeGetModuleSpecifier();
2813
3229
  const resolveExternalModuleName = makeResolveExternalModuleName(typeChecker);
2814
3230
  if (!(getModuleSpecifier && resolveExternalModuleName)) return;
2815
3231
  const importDeclaration = ts.findAncestor(element, (node) => ts.isImportDeclaration(node));
@@ -2885,7 +3301,7 @@ var importFromBarrel = createDiagnostic({
2885
3301
  unbarrelledFileName
2886
3302
  } = result;
2887
3303
  report({
2888
- node,
3304
+ location: node,
2889
3305
  messageText: `Importing from barrel module ${barrelModuleName} is not allowed.`,
2890
3306
  fixes: [
2891
3307
  {
@@ -2999,7 +3415,7 @@ var leakingRequirements = createDiagnostic({
2999
3415
  function reportLeakingRequirements(node, requirements) {
3000
3416
  if (requirements.length === 0) return;
3001
3417
  report({
3002
- node,
3418
+ location: node,
3003
3419
  messageText: `This Service is leaking the ${requirements.map((_) => typeChecker.typeToString(_)).join(" | ")} requirement.
3004
3420
  If these requirements cannot be cached and are expected to be provided per method invocation (e.g. HttpServerRequest), you can safely disable this diagnostic for this line through quickfixes.
3005
3421
  More info at https://effect.website/docs/requirements-management/layers/#avoiding-requirement-leakage`,
@@ -3079,7 +3495,7 @@ var missingEffectContext = createDiagnostic({
3079
3495
  map3(
3080
3496
  (missingTypes) => missingTypes.length > 0 ? report(
3081
3497
  {
3082
- node,
3498
+ location: node,
3083
3499
  messageText: `Missing '${sortTypes(missingTypes).map((_) => typeChecker.typeToString(_)).join(" | ")}' in the expected Effect context.`,
3084
3500
  fixes: []
3085
3501
  }
@@ -3099,18 +3515,15 @@ var missingEffectError = createDiagnostic({
3099
3515
  severity: "error",
3100
3516
  apply: fn("missingEffectError.apply")(function* (sourceFile, report) {
3101
3517
  const ts = yield* service(TypeScriptApi);
3518
+ const tsUtils = yield* service(TypeScriptUtils);
3102
3519
  const typeChecker = yield* service(TypeCheckerApi);
3103
3520
  const typeParser = yield* service(TypeParser);
3104
3521
  const typeOrder = yield* deterministicTypeOrder;
3105
- const effectModuleIdentifier = yield* pipe(
3106
- findImportedModuleIdentifierByPackageAndNameOrBarrel(
3107
- sourceFile,
3108
- "effect",
3109
- "Effect"
3110
- ),
3111
- map3((_) => _.text),
3112
- orElse2(() => succeed("Effect"))
3113
- );
3522
+ const effectModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
3523
+ sourceFile,
3524
+ "effect",
3525
+ "Effect"
3526
+ ) || "Effect";
3114
3527
  const createDieMessage = (message) => ts.factory.createCallExpression(
3115
3528
  ts.factory.createPropertyAccessExpression(
3116
3529
  ts.factory.createIdentifier(effectModuleIdentifier),
@@ -3212,7 +3625,7 @@ var missingEffectError = createDiagnostic({
3212
3625
  }
3213
3626
  report(
3214
3627
  {
3215
- node,
3628
+ location: node,
3216
3629
  messageText: `Missing '${sortTypes(result.missingErrorTypes).map((_) => typeChecker.typeToString(_)).join(" | ")}' in the expected Effect errors.`,
3217
3630
  fixes
3218
3631
  }
@@ -3276,7 +3689,7 @@ var missingReturnYieldStar = createDiagnostic({
3276
3689
  })
3277
3690
  }] : [];
3278
3691
  report({
3279
- node,
3692
+ location: node,
3280
3693
  messageText: `Yielded Effect never succeeds, so it is best to use a 'return yield*' instead.`,
3281
3694
  fixes: fix
3282
3695
  });
@@ -3332,7 +3745,7 @@ var missingStarInYieldEffectGen = createDiagnostic({
3332
3745
  }
3333
3746
  brokenGenerators.forEach(
3334
3747
  (node) => report({
3335
- node,
3748
+ location: node,
3336
3749
  messageText: `Seems like you used yield instead of yield* inside this Effect.gen.`,
3337
3750
  fixes: []
3338
3751
  })
@@ -3354,7 +3767,7 @@ var missingStarInYieldEffectGen = createDiagnostic({
3354
3767
  })
3355
3768
  }] : [];
3356
3769
  report({
3357
- node,
3770
+ location: node,
3358
3771
  messageText: `When yielding Effects inside Effect.gen, you should use yield* instead of yield.`,
3359
3772
  fixes: fix
3360
3773
  });
@@ -3369,26 +3782,19 @@ var multipleEffectProvide = createDiagnostic({
3369
3782
  severity: "warning",
3370
3783
  apply: fn("multipleEffectProvide.apply")(function* (sourceFile, report) {
3371
3784
  const ts = yield* service(TypeScriptApi);
3785
+ const tsUtils = yield* service(TypeScriptUtils);
3372
3786
  const typeChecker = yield* service(TypeCheckerApi);
3373
3787
  const typeParser = yield* service(TypeParser);
3374
- const effectModuleIdentifier = yield* pipe(
3375
- findImportedModuleIdentifierByPackageAndNameOrBarrel(
3376
- sourceFile,
3377
- "effect",
3378
- "Effect"
3379
- ),
3380
- map3((_) => _.text),
3381
- orElse2(() => succeed("Effect"))
3382
- );
3383
- const layerModuleIdentifier = yield* pipe(
3384
- findImportedModuleIdentifierByPackageAndNameOrBarrel(
3385
- sourceFile,
3386
- "effect",
3387
- "Layer"
3388
- ),
3389
- map3((_) => _.text),
3390
- orElse2(() => succeed("Layer"))
3391
- );
3788
+ const effectModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
3789
+ sourceFile,
3790
+ "effect",
3791
+ "Effect"
3792
+ ) || "Effect";
3793
+ const layerModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
3794
+ sourceFile,
3795
+ "effect",
3796
+ "Layer"
3797
+ ) || "Layer";
3392
3798
  const parseEffectProvideLayer = (node) => {
3393
3799
  if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.isIdentifier(node.expression.name) && node.expression.name.text === "provide" && node.arguments.length > 0) {
3394
3800
  const layer = node.arguments[0];
@@ -3418,7 +3824,7 @@ var multipleEffectProvide = createDiagnostic({
3418
3824
  for (const chunk of previousLayers) {
3419
3825
  if (chunk.length < 2) continue;
3420
3826
  report({
3421
- node: chunk[0].node,
3827
+ location: chunk[0].node,
3422
3828
  messageText: "Avoid chaining Effect.provide calls, as this can lead to service lifecycle issues. Instead, merge layers and provide them in a single call.",
3423
3829
  fixes: [{
3424
3830
  fixName: "multipleEffectProvide_fix",
@@ -3466,6 +3872,327 @@ var multipleEffectProvide = createDiagnostic({
3466
3872
  })
3467
3873
  });
3468
3874
 
3875
+ // src/refactors/writeTagClassAccessors.ts
3876
+ var generate = fn("writeTagClassAccessors.generate")(function* (sourceFile, service2, className, atLocation, involvedMembers) {
3877
+ const ts = yield* service(TypeScriptApi);
3878
+ const tsUtils = yield* service(TypeScriptUtils);
3879
+ const typeChecker = yield* service(TypeCheckerApi);
3880
+ const typeParser = yield* service(TypeParser);
3881
+ const changeTracker = yield* service(ChangeTracker);
3882
+ const insertLocation = atLocation.members.length > 0 ? atLocation.members[0].pos : atLocation.getEnd() - 1;
3883
+ const effectIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
3884
+ sourceFile,
3885
+ "effect",
3886
+ "Effect"
3887
+ ) || "Effect";
3888
+ const createFunctionProperty = (className2, propertyName, type, forceAny) => {
3889
+ const arrowBody = ts.factory.createCallExpression(
3890
+ ts.factory.createPropertyAccessExpression(
3891
+ ts.factory.createIdentifier(effectIdentifier),
3892
+ "andThen"
3893
+ ),
3894
+ void 0,
3895
+ [
3896
+ ts.factory.createIdentifier(className2.text),
3897
+ ts.factory.createArrowFunction(
3898
+ void 0,
3899
+ void 0,
3900
+ [ts.factory.createParameterDeclaration(
3901
+ void 0,
3902
+ void 0,
3903
+ "_",
3904
+ void 0,
3905
+ forceAny ? ts.factory.createTypeReferenceNode("any") : void 0
3906
+ )],
3907
+ void 0,
3908
+ void 0,
3909
+ ts.factory.createCallExpression(
3910
+ ts.factory.createPropertyAccessExpression(
3911
+ ts.factory.createIdentifier("_"),
3912
+ propertyName
3913
+ ),
3914
+ void 0,
3915
+ [
3916
+ ts.factory.createSpreadElement(ts.factory.createIdentifier("args"))
3917
+ ]
3918
+ )
3919
+ )
3920
+ ]
3921
+ );
3922
+ return ts.factory.createPropertyDeclaration(
3923
+ [ts.factory.createModifier(ts.SyntaxKind.StaticKeyword)],
3924
+ propertyName,
3925
+ void 0,
3926
+ type,
3927
+ ts.factory.createArrowFunction(
3928
+ void 0,
3929
+ void 0,
3930
+ [ts.factory.createParameterDeclaration(
3931
+ void 0,
3932
+ ts.factory.createToken(ts.SyntaxKind.DotDotDotToken),
3933
+ "args",
3934
+ void 0,
3935
+ forceAny ? ts.factory.createArrayTypeNode(ts.factory.createTypeReferenceNode("any")) : void 0
3936
+ )],
3937
+ void 0,
3938
+ void 0,
3939
+ forceAny ? ts.factory.createAsExpression(arrowBody, ts.factory.createTypeReferenceNode("any")) : arrowBody
3940
+ )
3941
+ );
3942
+ };
3943
+ const generateReturnType = (type, atLocation2, className2) => pipe(
3944
+ typeParser.effectType(type, atLocation2),
3945
+ flatMap2((returnedEffect) => {
3946
+ const contextType = returnedEffect.R.flags & ts.TypeFlags.Never ? ts.factory.createTypeReferenceNode(className2.text) : ts.factory.createUnionTypeNode(
3947
+ [
3948
+ ts.factory.createTypeReferenceNode(className2.text),
3949
+ typeChecker.typeToTypeNode(returnedEffect.R, atLocation2, ts.NodeBuilderFlags.NoTruncation)
3950
+ ]
3951
+ );
3952
+ const successType = typeChecker.typeToTypeNode(
3953
+ returnedEffect.A,
3954
+ atLocation2,
3955
+ ts.NodeBuilderFlags.NoTruncation
3956
+ );
3957
+ if (!successType) return fail("error generating success type");
3958
+ const failureType = typeChecker.typeToTypeNode(
3959
+ returnedEffect.E,
3960
+ atLocation2,
3961
+ ts.NodeBuilderFlags.NoTruncation
3962
+ );
3963
+ if (!failureType) return fail("error generating failure type");
3964
+ const typeNode = ts.factory.createTypeReferenceNode(
3965
+ ts.factory.createQualifiedName(
3966
+ ts.factory.createIdentifier(effectIdentifier),
3967
+ ts.factory.createIdentifier("Effect")
3968
+ ),
3969
+ [successType, failureType, contextType]
3970
+ );
3971
+ return succeed(typeNode);
3972
+ }),
3973
+ orElse2(
3974
+ () => pipe(
3975
+ typeParser.promiseLike(type, atLocation2),
3976
+ flatMap2(({ type: type2 }) => {
3977
+ const successType = typeChecker.typeToTypeNode(
3978
+ type2,
3979
+ atLocation2,
3980
+ ts.NodeBuilderFlags.NoTruncation
3981
+ );
3982
+ if (!successType) return fail("error generating success type");
3983
+ return succeed(ts.factory.createTypeReferenceNode(
3984
+ ts.factory.createQualifiedName(
3985
+ ts.factory.createIdentifier(effectIdentifier),
3986
+ ts.factory.createIdentifier("Effect")
3987
+ ),
3988
+ [
3989
+ successType,
3990
+ ts.factory.createTypeReferenceNode(
3991
+ ts.factory.createQualifiedName(
3992
+ ts.factory.createIdentifier("Cause"),
3993
+ ts.factory.createIdentifier("UnknownException")
3994
+ )
3995
+ ),
3996
+ ts.factory.createTypeReferenceNode(className2.text)
3997
+ ]
3998
+ ));
3999
+ })
4000
+ )
4001
+ ),
4002
+ orElse2(() => {
4003
+ const successType = typeChecker.typeToTypeNode(type, atLocation2, ts.NodeBuilderFlags.NoTruncation);
4004
+ if (!successType) return fail("error generating success type");
4005
+ const typeNode = ts.factory.createTypeReferenceNode(
4006
+ ts.factory.createQualifiedName(
4007
+ ts.factory.createIdentifier(effectIdentifier),
4008
+ ts.factory.createIdentifier("Effect")
4009
+ ),
4010
+ [
4011
+ successType,
4012
+ ts.factory.createTypeReferenceNode("never"),
4013
+ ts.factory.createTypeReferenceNode(className2.text)
4014
+ ]
4015
+ );
4016
+ return succeed(typeNode);
4017
+ })
4018
+ );
4019
+ const proxySignature = (signature, atLocation2, className2) => gen(function* () {
4020
+ const signatureDeclaration = typeChecker.signatureToSignatureDeclaration(
4021
+ signature,
4022
+ ts.SyntaxKind.FunctionType,
4023
+ atLocation2,
4024
+ ts.NodeBuilderFlags.NoTruncation
4025
+ );
4026
+ if (!signatureDeclaration) return yield* fail("error generating signature");
4027
+ const returnType = yield* generateReturnType(signature.getReturnType(), atLocation2, className2);
4028
+ return ts.factory.createFunctionTypeNode(
4029
+ signatureDeclaration.typeParameters,
4030
+ signatureDeclaration.parameters,
4031
+ returnType
4032
+ );
4033
+ });
4034
+ for (const { property, propertyType } of involvedMembers) {
4035
+ const callSignatures = [];
4036
+ let propertyDeclaration = void 0;
4037
+ for (const signature of propertyType.getCallSignatures()) {
4038
+ yield* pipe(
4039
+ proxySignature(signature, atLocation, className),
4040
+ map3((sig) => {
4041
+ callSignatures.push(sig);
4042
+ }),
4043
+ ignore
4044
+ );
4045
+ }
4046
+ const allSignatures = ts.factory.createIntersectionTypeNode(callSignatures);
4047
+ const type = tsUtils.simplifyTypeNode(allSignatures);
4048
+ propertyDeclaration = createFunctionProperty(className, property.getName(), type, callSignatures.length > 1);
4049
+ const oldProperty = atLocation.members.filter(ts.isPropertyDeclaration).find((p) => {
4050
+ const symbol3 = typeChecker.getSymbolAtLocation(p.name);
4051
+ return symbol3?.getName() === property.getName();
4052
+ });
4053
+ if (oldProperty) {
4054
+ changeTracker.deleteRange(sourceFile, {
4055
+ pos: oldProperty.getStart(sourceFile),
4056
+ end: oldProperty.getEnd()
4057
+ });
4058
+ changeTracker.insertNodeAt(sourceFile, oldProperty.getStart(sourceFile), propertyDeclaration);
4059
+ } else {
4060
+ changeTracker.insertNodeAt(sourceFile, insertLocation, propertyDeclaration, { suffix: "\n" });
4061
+ }
4062
+ }
4063
+ });
4064
+ var parse2 = fn("writeTagClassAccessors.parse")(function* (node) {
4065
+ const ts = yield* service(TypeScriptApi);
4066
+ const typeChecker = yield* service(TypeCheckerApi);
4067
+ const typeParser = yield* service(TypeParser);
4068
+ if (!ts.isClassDeclaration(node)) return yield* fail("not a class declaration");
4069
+ const { Service, accessors: accessors2, className } = yield* pipe(
4070
+ typeParser.extendsEffectService(node),
4071
+ orElse2(() => fail("not a class extending Effect.Service call"))
4072
+ );
4073
+ if (accessors2 !== true) return yield* fail("accessors are not enabled in the Effect.Service call");
4074
+ const involvedMembers = [];
4075
+ for (const property of typeChecker.getPropertiesOfType(Service)) {
4076
+ const propertyType = typeChecker.getTypeOfSymbolAtLocation(property, node);
4077
+ const callSignatures = propertyType.getCallSignatures();
4078
+ if (callSignatures.length > 0) {
4079
+ const withTypeParameters = callSignatures.filter((_) => _.typeParameters && _.typeParameters.length > 0);
4080
+ if (callSignatures.length > 1 || withTypeParameters.length > 0) involvedMembers.push({ property, propertyType });
4081
+ }
4082
+ }
4083
+ const hash2 = involvedMembers.map(({ property, propertyType }) => {
4084
+ return property.getName() + ": " + typeChecker.typeToString(propertyType);
4085
+ }).concat([className.text]).join("\n");
4086
+ return { Service, className, atLocation: node, hash: cyrb53(hash2), involvedMembers };
4087
+ });
4088
+ var writeTagClassAccessors = createRefactor({
4089
+ name: "writeTagClassAccessors",
4090
+ description: "Implement accessors methods with generics or multiple signatures",
4091
+ apply: fn("writeTagClassAccessors.apply")(function* (sourceFile, textRange) {
4092
+ const ts = yield* service(TypeScriptApi);
4093
+ const tsUtils = yield* service(TypeScriptUtils);
4094
+ const typeChecker = yield* service(TypeCheckerApi);
4095
+ const typeParser = yield* service(TypeParser);
4096
+ const parseNode = (node) => pipe(
4097
+ parse2(node),
4098
+ map3(({ Service, atLocation, className, involvedMembers }) => ({
4099
+ kind: "refactor.rewrite.effect.writeTagClassAccessors",
4100
+ description: "Implement Service accessors",
4101
+ apply: pipe(
4102
+ generate(sourceFile, Service, className, atLocation, involvedMembers),
4103
+ provideService(TypeScriptUtils, tsUtils),
4104
+ provideService(TypeParser, typeParser),
4105
+ provideService(TypeCheckerApi, typeChecker),
4106
+ provideService(TypeScriptApi, ts)
4107
+ )
4108
+ }))
4109
+ );
4110
+ const parentNodes = tsUtils.getAncestorNodesInRange(sourceFile, textRange);
4111
+ return yield* pipe(
4112
+ firstSuccessOf(parentNodes.map(parseNode)),
4113
+ orElse2(() => fail(new RefactorNotApplicableError()))
4114
+ );
4115
+ })
4116
+ });
4117
+
4118
+ // src/codegens/accessors.ts
4119
+ var accessors = createCodegen({
4120
+ name: "accessors",
4121
+ apply: fn("accessors.apply")(function* (sourceFile, textRange) {
4122
+ const ts = yield* service(TypeScriptApi);
4123
+ const tsUtils = yield* service(TypeScriptUtils);
4124
+ const typeChecker = yield* service(TypeCheckerApi);
4125
+ const typeParser = yield* service(TypeParser);
4126
+ const nodeAndCommentRange = tsUtils.findNodeWithLeadingCommentAtPosition(sourceFile, textRange.pos);
4127
+ if (!nodeAndCommentRange) return yield* fail(new CodegenNotApplicableError("no node and comment range"));
4128
+ return yield* pipe(
4129
+ parse2(nodeAndCommentRange.node),
4130
+ map3(
4131
+ (_) => ({
4132
+ hash: _.hash,
4133
+ description: "Generate accessors for the service",
4134
+ apply: pipe(
4135
+ generate(sourceFile, _.Service, _.className, _.atLocation, _.involvedMembers),
4136
+ provideService(TypeScriptApi, ts),
4137
+ provideService(TypeScriptUtils, tsUtils),
4138
+ provideService(TypeCheckerApi, typeChecker),
4139
+ provideService(TypeParser, typeParser)
4140
+ )
4141
+ })
4142
+ ),
4143
+ orElse2((cause) => fail(new CodegenNotApplicableError(cause)))
4144
+ );
4145
+ })
4146
+ });
4147
+
4148
+ // src/codegens.ts
4149
+ var codegens = [accessors];
4150
+
4151
+ // src/diagnostics/outdatedEffectCodegen.ts
4152
+ var outdatedEffectCodegen = createDiagnostic({
4153
+ name: "outdatedEffectCodegen",
4154
+ code: 19,
4155
+ severity: "warning",
4156
+ apply: fn("outdatedEffectCodegen.apply")(function* (sourceFile, _report) {
4157
+ const codegensWithRanges = yield* getCodegensForSourceFile(codegens, sourceFile);
4158
+ for (const { codegen, hash: hash2, range } of codegensWithRanges) {
4159
+ yield* pipe(
4160
+ getEditsForCodegen([codegen], sourceFile, range),
4161
+ map3((applicable) => {
4162
+ if (applicable.hash !== hash2) {
4163
+ _report({
4164
+ location: range,
4165
+ messageText: `Codegen ${codegen.name} result is outdated`,
4166
+ fixes: [
4167
+ {
4168
+ fixName: "outdatedEffectCodegen_fix",
4169
+ description: `Re-run ${codegen.name}`,
4170
+ apply: applicable.apply
4171
+ },
4172
+ {
4173
+ fixName: "outdatedEffectCodegen_ignore",
4174
+ description: `Ignore this ${codegen.name} update`,
4175
+ apply: applicable.ignore
4176
+ }
4177
+ ]
4178
+ });
4179
+ }
4180
+ }),
4181
+ orElse2(
4182
+ (e) => sync(() => {
4183
+ _report({
4184
+ location: range,
4185
+ messageText: `Codegen ${codegen.name} is not applicable here: ${e.cause}`,
4186
+ fixes: []
4187
+ });
4188
+ })
4189
+ ),
4190
+ ignore
4191
+ );
4192
+ }
4193
+ })
4194
+ });
4195
+
3469
4196
  // src/diagnostics/returnEffectInGen.ts
3470
4197
  var returnEffectInGen = createDiagnostic({
3471
4198
  name: "returnEffectInGen",
@@ -3517,7 +4244,7 @@ var returnEffectInGen = createDiagnostic({
3517
4244
  })
3518
4245
  }] : [];
3519
4246
  report({
3520
- node,
4247
+ location: node,
3521
4248
  messageText: `You are returning an Effect-able type inside a generator function, and will result in nested Effect<Effect<...>>.
3522
4249
  Maybe you wanted to return yield* instead?
3523
4250
  Nested Effect-able types may be intended if you plan to later manually flatten or unwrap this Effect, if so you can safely disable this diagnostic for this line through quickfixes.`,
@@ -3540,17 +4267,14 @@ var scopeInLayerEffect = createDiagnostic({
3540
4267
  severity: "warning",
3541
4268
  apply: fn("scopeInLayerEffect.apply")(function* (sourceFile, report) {
3542
4269
  const ts = yield* service(TypeScriptApi);
4270
+ const tsUtils = yield* service(TypeScriptUtils);
3543
4271
  const typeChecker = yield* service(TypeCheckerApi);
3544
4272
  const typeParser = yield* service(TypeParser);
3545
- const layerModuleIdentifier = yield* pipe(
3546
- findImportedModuleIdentifierByPackageAndNameOrBarrel(
3547
- sourceFile,
3548
- "effect",
3549
- "Layer"
3550
- ),
3551
- map3((_) => _.text),
3552
- orElse2(() => succeed("Layer"))
3553
- );
4273
+ const layerModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
4274
+ sourceFile,
4275
+ "effect",
4276
+ "Layer"
4277
+ ) || "Layer";
3554
4278
  function parseLayerEffectApiCall(node) {
3555
4279
  if (!ts.isCallExpression(node)) return;
3556
4280
  const expression = node.expression;
@@ -3576,7 +4300,7 @@ var scopeInLayerEffect = createDiagnostic({
3576
4300
  firstSuccessOf(entries.map((type2) => typeParser.scopeType(type2, node))),
3577
4301
  map3(
3578
4302
  () => report({
3579
- node,
4303
+ location: node,
3580
4304
  messageText: `Seems like you are constructing a layer with a scope in the requirements.
3581
4305
  Consider using "scoped" instead to get rid of the scope in the requirements.`,
3582
4306
  fixes: methodIdentifier ? [{
@@ -3692,7 +4416,7 @@ var strictBooleanExpressions = createDiagnostic({
3692
4416
  if (type.flags & ts.TypeFlags.BooleanLiteral) continue;
3693
4417
  const typeName = typeChecker.typeToString(type);
3694
4418
  report({
3695
- node: nodeToCheck,
4419
+ location: nodeToCheck,
3696
4420
  messageText: `Unexpected \`${typeName}\` type in condition, expected strictly a boolean instead.`,
3697
4421
  fixes: []
3698
4422
  });
@@ -3734,7 +4458,7 @@ var tryCatchInEffectGen = createDiagnostic({
3734
4458
  orElse2(() => typeParser.effectFnGen(effectGenNode)),
3735
4459
  map3(() => {
3736
4460
  report({
3737
- node,
4461
+ location: node,
3738
4462
  messageText: "Avoid using try/catch inside Effect generators. Use Effect's error handling mechanisms instead (e.g., Effect.try, Effect.tryPromise, Effect.catchAll, Effect.catchTag).",
3739
4463
  fixes: []
3740
4464
  });
@@ -3769,7 +4493,7 @@ var unnecessaryEffectGen = createDiagnostic({
3769
4493
  typeParser.unnecessaryEffectGen(node),
3770
4494
  map3(
3771
4495
  ({ replacementNode }) => report({
3772
- node,
4496
+ location: node,
3773
4497
  messageText: `This Effect.gen contains a single return statement.`,
3774
4498
  fixes: [{
3775
4499
  fixName: "unnecessaryEffectGen_fix",
@@ -3813,7 +4537,7 @@ var unnecessaryPipe = createDiagnostic({
3813
4537
  map3(({ args: args2, subject }) => {
3814
4538
  if (args2.length === 0) {
3815
4539
  report({
3816
- node,
4540
+ location: node,
3817
4541
  messageText: `This pipe call contains no arguments.`,
3818
4542
  fixes: [{
3819
4543
  fixName: "unnecessaryPipe_fix",
@@ -3860,7 +4584,7 @@ var unnecessaryPipeChain = createDiagnostic({
3860
4584
  ),
3861
4585
  map3(({ innerCall, pipeCall }) => {
3862
4586
  report({
3863
- node,
4587
+ location: node,
3864
4588
  messageText: `Chained pipe calls can be simplified to a single pipe call`,
3865
4589
  fixes: [{
3866
4590
  fixName: "unnecessaryPipeChain_fix",
@@ -3909,8 +4633,64 @@ var unnecessaryPipeChain = createDiagnostic({
3909
4633
  })
3910
4634
  });
3911
4635
 
4636
+ // src/diagnostics/unsupportedServiceAccessors.ts
4637
+ var unsupportedServiceAccessors = createDiagnostic({
4638
+ name: "unsupportedServiceAccessors",
4639
+ code: 21,
4640
+ severity: "warning",
4641
+ apply: fn("unsupportedServiceAccessors.apply")(function* (sourceFile, report) {
4642
+ const ts = yield* service(TypeScriptApi);
4643
+ const nodeToVisit = [];
4644
+ const appendNodeToVisit = (node) => {
4645
+ nodeToVisit.push(node);
4646
+ return void 0;
4647
+ };
4648
+ ts.forEachChild(sourceFile, appendNodeToVisit);
4649
+ while (nodeToVisit.length > 0) {
4650
+ const node = nodeToVisit.shift();
4651
+ ts.forEachChild(node, appendNodeToVisit);
4652
+ if (ts.isClassDeclaration(node)) {
4653
+ const parseResult = yield* pipe(
4654
+ parse2(node),
4655
+ orElse2(() => succeed(null))
4656
+ );
4657
+ if (parseResult && parseResult.involvedMembers.length > 0) {
4658
+ const existingStaticMembers = /* @__PURE__ */ new Set();
4659
+ node.members?.forEach((member) => {
4660
+ if (ts.isPropertyDeclaration(member) && member.modifiers?.some((mod) => mod.kind === ts.SyntaxKind.StaticKeyword)) {
4661
+ if (member.name && ts.isIdentifier(member.name)) {
4662
+ existingStaticMembers.add(member.name.text);
4663
+ }
4664
+ }
4665
+ });
4666
+ const missingMembers = parseResult.involvedMembers.filter(
4667
+ ({ property }) => !existingStaticMembers.has(property.getName())
4668
+ );
4669
+ if (missingMembers.length > 0) {
4670
+ const memberNames = missingMembers.map(({ property }) => `'${property.getName()}'`).join(", ");
4671
+ report({
4672
+ location: parseResult.className,
4673
+ messageText: `Even if accessors are enabled, accessors for ${memberNames} won't be available because the signature have generic type parameters or multiple call signatures.`,
4674
+ fixes: [{
4675
+ fixName: "unsupportedServiceAccessors_enableCodegen",
4676
+ description: "Enable accessors codegen",
4677
+ apply: gen(function* () {
4678
+ const changeTracker = yield* service(ChangeTracker);
4679
+ const comment = "// @effect-codegens accessors\n";
4680
+ changeTracker.insertText(sourceFile, node.getStart(sourceFile), comment);
4681
+ })
4682
+ }]
4683
+ });
4684
+ }
4685
+ }
4686
+ }
4687
+ }
4688
+ })
4689
+ });
4690
+
3912
4691
  // src/diagnostics.ts
3913
4692
  var diagnostics = [
4693
+ classSelfMismatch,
3914
4694
  duplicatePackage,
3915
4695
  missingEffectContext,
3916
4696
  missingEffectError,
@@ -3928,7 +4708,9 @@ var diagnostics = [
3928
4708
  effectInVoidSuccess,
3929
4709
  unnecessaryPipeChain,
3930
4710
  strictBooleanExpressions,
3931
- multipleEffectProvide
4711
+ multipleEffectProvide,
4712
+ outdatedEffectCodegen,
4713
+ unsupportedServiceAccessors
3932
4714
  ];
3933
4715
 
3934
4716
  // src/transform.ts
@@ -3937,14 +4719,11 @@ function transform_default(program, pluginConfig, { addDiagnostic, ts: tsInstanc
3937
4719
  return (sourceFile) => {
3938
4720
  pipe(
3939
4721
  getSemanticDiagnosticsWithCodeFixes(diagnostics, sourceFile),
3940
- provideService(TypeScriptApi, tsInstance),
3941
- provideService(TypeScriptProgram, program),
4722
+ nanoLayer2,
4723
+ nanoLayer,
3942
4724
  provideService(TypeCheckerApi, program.getTypeChecker()),
3943
- provideService(TypeParser, make2(tsInstance, program.getTypeChecker())),
3944
- provideService(
3945
- TypeCheckerApiCache,
3946
- makeTypeCheckerApiCache()
3947
- ),
4725
+ provideService(TypeScriptProgram, program),
4726
+ provideService(TypeScriptApi, tsInstance),
3948
4727
  provideService(
3949
4728
  LanguageServicePluginOptions,
3950
4729
  parse(pluginConfig)