@effect/language-service 0.5.1 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/index.js +334 -199
  2. package/index.js.map +1 -1
  3. package/package.json +1 -1
package/index.js CHANGED
@@ -115,6 +115,7 @@ var globalValue = (id, compute) => {
115
115
  };
116
116
 
117
117
  // node_modules/.pnpm/effect@3.12.5/node_modules/effect/dist/esm/Predicate.js
118
+ var isBoolean = (input) => typeof input === "boolean";
118
119
  var isFunction2 = isFunction;
119
120
  var isRecordOrArray = (input) => typeof input === "object" && input !== null;
120
121
  var isObject = (input) => isRecordOrArray(input) || isFunction2(input);
@@ -814,12 +815,14 @@ function effectGen(ts, typeChecker) {
814
815
  if (!ts.isPropertyAccessExpression(node.expression)) return yield* none2();
815
816
  const propertyAccess = node.expression;
816
817
  if (propertyAccess.name.text !== "gen") return yield* none2();
817
- return yield* importedEffectModule(ts, typeChecker)(propertyAccess.expression).pipe(
818
- map(() => ({
819
- body: generatorFunction.body,
820
- functionStar: generatorFunction.getFirstToken()
821
- }))
822
- );
818
+ const effectModule = yield* importedEffectModule(ts, typeChecker)(propertyAccess.expression);
819
+ return {
820
+ node,
821
+ effectModule,
822
+ generatorFunction,
823
+ body: generatorFunction.body,
824
+ functionStar: generatorFunction.getFirstToken()
825
+ };
823
826
  });
824
827
  }
825
828
  function effectFnUntracedGen(ts, typeChecker) {
@@ -832,12 +835,14 @@ function effectFnUntracedGen(ts, typeChecker) {
832
835
  if (!ts.isPropertyAccessExpression(node.expression)) return yield* none2();
833
836
  const propertyAccess = node.expression;
834
837
  if (propertyAccess.name.text !== "fnUntraced") return yield* none2();
835
- return yield* importedEffectModule(ts, typeChecker)(propertyAccess.expression).pipe(
836
- map(() => ({
837
- body: generatorFunction.body,
838
- functionStar: generatorFunction.getFirstToken()
839
- }))
840
- );
838
+ const effectModule = yield* importedEffectModule(ts, typeChecker)(propertyAccess.expression);
839
+ return {
840
+ node,
841
+ effectModule,
842
+ generatorFunction,
843
+ body: generatorFunction.body,
844
+ functionStar: generatorFunction.getFirstToken()
845
+ };
841
846
  });
842
847
  }
843
848
  function effectFnGen(ts, typeChecker) {
@@ -851,71 +856,16 @@ function effectFnGen(ts, typeChecker) {
851
856
  if (!ts.isPropertyAccessExpression(expressionToTest)) return yield* none2();
852
857
  const propertyAccess = expressionToTest;
853
858
  if (propertyAccess.name.text !== "fn") return yield* none2();
854
- return yield* importedEffectModule(ts, typeChecker)(propertyAccess.expression).pipe(
855
- map(() => ({
856
- body: generatorFunction.body,
857
- functionStar: generatorFunction.getFirstToken()
858
- }))
859
- );
859
+ const effectModule = yield* importedEffectModule(ts, typeChecker)(propertyAccess.expression);
860
+ return {
861
+ node,
862
+ generatorFunction,
863
+ effectModule,
864
+ body: generatorFunction.body,
865
+ functionStar: generatorFunction.getFirstToken()
866
+ };
860
867
  });
861
868
  }
862
- function expectedAndRealType(ts, typeChecker) {
863
- return (node) => {
864
- if (ts.isVariableDeclaration(node) && node.initializer) {
865
- const expectedType = typeChecker.getTypeAtLocation(node.name);
866
- const realType = typeChecker.getTypeAtLocation(node.initializer);
867
- return [[node.name, expectedType, node.initializer, realType]];
868
- }
869
- if (ts.isCallExpression(node)) {
870
- const resolvedSignature = typeChecker.getResolvedSignature(node);
871
- if (resolvedSignature) {
872
- return resolvedSignature.getParameters().map((parameter, index) => {
873
- const expectedType = typeChecker.getTypeOfSymbolAtLocation(parameter, node);
874
- const realType = typeChecker.getTypeAtLocation(node.arguments[index]);
875
- return [node.arguments[index], expectedType, node.arguments[index], realType];
876
- });
877
- }
878
- }
879
- if (ts.isIdentifier(node) || ts.isStringLiteral(node) || ts.isNumericLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) {
880
- const parent = node.parent;
881
- if (ts.isObjectLiteralElement(parent)) {
882
- if (ts.isObjectLiteralExpression(parent.parent) && parent.name === node) {
883
- const type = typeChecker.getContextualType(parent.parent);
884
- if (type) {
885
- const symbol3 = typeChecker.getPropertyOfType(type, node.text);
886
- if (symbol3) {
887
- const expectedType = typeChecker.getTypeOfSymbolAtLocation(symbol3, node);
888
- const realType = typeChecker.getTypeAtLocation(node);
889
- return [[node, expectedType, node, realType]];
890
- }
891
- }
892
- }
893
- }
894
- }
895
- if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
896
- const expectedType = typeChecker.getTypeAtLocation(node.left);
897
- const realType = typeChecker.getTypeAtLocation(node.right);
898
- return [[node.left, expectedType, node.right, realType]];
899
- }
900
- if (ts.isReturnStatement(node) && node.expression) {
901
- const expectedType = typeChecker.getContextualType(node.expression);
902
- const realType = typeChecker.getTypeAtLocation(node.expression);
903
- if (expectedType) return [[node, expectedType, node, realType]];
904
- }
905
- if (ts.isArrowFunction(node) && ts.isExpression(node.body)) {
906
- const body = node.body;
907
- const expectedType = typeChecker.getContextualType(body);
908
- const realType = typeChecker.getTypeAtLocation(body);
909
- if (expectedType) return [[body, expectedType, body, realType]];
910
- }
911
- if (ts.isSatisfiesExpression(node)) {
912
- const expectedType = typeChecker.getTypeAtLocation(node.type);
913
- const realType = typeChecker.getTypeAtLocation(node.expression);
914
- return [[node.expression, expectedType, node.expression, realType]];
915
- }
916
- return [];
917
- };
918
- }
919
869
 
920
870
  // src/diagnostics/floatingEffect.ts
921
871
  var floatingEffect = createDiagnostic({
@@ -958,6 +908,25 @@ var floatingEffect = createDiagnostic({
958
908
  // node_modules/.pnpm/effect@3.12.5/node_modules/effect/dist/esm/internal/array.js
959
909
  var isNonEmptyArray = (self) => self.length > 0;
960
910
 
911
+ // node_modules/.pnpm/effect@3.12.5/node_modules/effect/dist/esm/Iterable.js
912
+ var findFirst = /* @__PURE__ */ dual(2, (self, f) => {
913
+ let i = 0;
914
+ for (const a of self) {
915
+ const o = f(a, i);
916
+ if (isBoolean(o)) {
917
+ if (o) {
918
+ return some2(a);
919
+ }
920
+ } else {
921
+ if (isSome2(o)) {
922
+ return o;
923
+ }
924
+ }
925
+ i++;
926
+ }
927
+ return none2();
928
+ });
929
+
961
930
  // node_modules/.pnpm/effect@3.12.5/node_modules/effect/dist/esm/Array.js
962
931
  var fromIterable = (collection) => Array.isArray(collection) ? collection : Array.from(collection);
963
932
  var append = /* @__PURE__ */ dual(2, (self, last) => [...self, last]);
@@ -979,6 +948,7 @@ var unsafeGet = /* @__PURE__ */ dual(2, (self, index) => {
979
948
  var head = /* @__PURE__ */ get(0);
980
949
  var headNonEmpty = /* @__PURE__ */ unsafeGet(0);
981
950
  var tailNonEmpty = (self) => self.slice(1);
951
+ var findFirst2 = findFirst;
982
952
  var sort = /* @__PURE__ */ dual(2, (self, O) => {
983
953
  const out = Array.from(self);
984
954
  out.sort(O);
@@ -1033,71 +1003,8 @@ function toTextRange(positionOrRange) {
1033
1003
  function isNodeInRange(textRange) {
1034
1004
  return (node) => node.pos <= textRange.pos && node.end >= textRange.end;
1035
1005
  }
1036
- function findModuleNamedBindings(ts) {
1037
- return (sourceFile, moduleName) => fromNullable(ts.forEachChild(sourceFile, (node) => {
1038
- if (!ts.isImportDeclaration(node)) return;
1039
- const moduleSpecifier = node.moduleSpecifier;
1040
- if (!ts.isStringLiteral(moduleSpecifier)) return;
1041
- if (moduleSpecifier.text !== moduleName) return;
1042
- const importClause = node.importClause;
1043
- if (!importClause) return;
1044
- const namedBindings = importClause.namedBindings;
1045
- if (!namedBindings) return;
1046
- return namedBindings;
1047
- }));
1048
- }
1049
- function findModuleNamespaceImportIdentifierName(ts) {
1050
- return (sourceFile, moduleName) => pipe(
1051
- findModuleNamedBindings(ts)(sourceFile, moduleName),
1052
- map(
1053
- (namedBindings) => {
1054
- if (!ts.isNamespaceImport(namedBindings)) return;
1055
- return namedBindings.name.text;
1056
- }
1057
- ),
1058
- flatMap(fromNullable)
1059
- );
1060
- }
1061
- function findModuleNamedImportIdentifierName(ts) {
1062
- return (sourceFile, moduleName, namedImport) => pipe(
1063
- findModuleNamedBindings(ts)(sourceFile, moduleName),
1064
- map((namedBindings) => {
1065
- if (!ts.isNamedImports(namedBindings)) return;
1066
- for (const importSpecifier of namedBindings.elements) {
1067
- if (importSpecifier.propertyName?.getText() === namedImport) {
1068
- return importSpecifier.name?.escapedText || importSpecifier.propertyName?.getText();
1069
- }
1070
- }
1071
- }),
1072
- flatMap(fromNullable)
1073
- );
1074
- }
1075
- function findModuleImportIdentifierNameViaTypeChecker(ts, typeChecker) {
1076
- return (sourceFile, importName) => {
1077
- return fromNullable(ts.forEachChild(sourceFile, (node) => {
1078
- if (!ts.isImportDeclaration(node)) return;
1079
- if (!node.importClause) return;
1080
- const namedBindings = node.importClause.namedBindings;
1081
- if (!namedBindings) return;
1082
- if (ts.isNamespaceImport(namedBindings)) {
1083
- const symbol3 = typeChecker.getTypeAtLocation(namedBindings).getSymbol();
1084
- if (!symbol3 || !symbol3.exports) return;
1085
- if (!symbol3.exports.has(importName)) return;
1086
- return namedBindings.name.escapedText;
1087
- }
1088
- if (ts.isNamedImports(namedBindings)) {
1089
- for (const importSpecifier of namedBindings.elements) {
1090
- const symbol3 = typeChecker.getTypeAtLocation(importSpecifier).getSymbol();
1091
- if (!symbol3 || !symbol3.exports) return;
1092
- if (!symbol3.exports.has(importName)) return;
1093
- return importSpecifier.name?.escapedText || importSpecifier.propertyName?.getText();
1094
- }
1095
- }
1096
- }));
1097
- };
1098
- }
1099
1006
  function transformAsyncAwaitToEffectGen(ts) {
1100
- return (node, effectName, onAwait) => {
1007
+ return (node, effectModuleName, onAwait) => {
1101
1008
  function visitor(_) {
1102
1009
  if (ts.isAwaitExpression(_)) {
1103
1010
  const expression = ts.visitEachChild(_.expression, visitor, ts.nullTransformationContext);
@@ -1121,7 +1028,7 @@ function transformAsyncAwaitToEffectGen(ts) {
1121
1028
  );
1122
1029
  const effectGenCallExp = ts.factory.createCallExpression(
1123
1030
  ts.factory.createPropertyAccessExpression(
1124
- ts.factory.createIdentifier(effectName),
1031
+ ts.factory.createIdentifier(effectModuleName),
1125
1032
  "gen"
1126
1033
  ),
1127
1034
  void 0,
@@ -1197,17 +1104,24 @@ function removeReturnTypeAnnotation(ts, changes) {
1197
1104
  }
1198
1105
  };
1199
1106
  }
1200
- function getEffectModuleIdentifier(ts, typeChecker) {
1201
- return (sourceFile) => pipe(
1202
- findModuleNamespaceImportIdentifierName(ts)(sourceFile, "effect/Effect"),
1203
- orElse(() => findModuleNamedImportIdentifierName(ts)(sourceFile, "effect", "Effect")),
1204
- orElse(
1205
- () => findModuleImportIdentifierNameViaTypeChecker(ts, typeChecker)(sourceFile, "Effect")
1206
- ),
1207
- getOrElse(
1208
- () => "Effect"
1209
- )
1210
- );
1107
+ function findImportedModuleIdentifier(ts) {
1108
+ return (test) => (sourceFile) => {
1109
+ for (const statement of sourceFile.statements) {
1110
+ if (!ts.isImportDeclaration(statement)) continue;
1111
+ const importClause = statement.importClause;
1112
+ if (!importClause) continue;
1113
+ const namedBindings = importClause.namedBindings;
1114
+ if (!namedBindings) continue;
1115
+ if (ts.isNamespaceImport(namedBindings)) {
1116
+ if (test(namedBindings.name)) return some2(namedBindings.name);
1117
+ } else if (ts.isNamedImports(namedBindings)) {
1118
+ for (const importSpecifier of namedBindings.elements) {
1119
+ if (test(importSpecifier.name)) return some2(importSpecifier.name);
1120
+ }
1121
+ }
1122
+ }
1123
+ return none2();
1124
+ };
1211
1125
  }
1212
1126
  function simplifyTypeNode(ts) {
1213
1127
  function collectCallable(typeNode) {
@@ -1278,6 +1192,35 @@ function deterministicTypeOrder(ts, typeChecker) {
1278
1192
  return 0;
1279
1193
  });
1280
1194
  }
1195
+ function tryPreserveDeclarationSemantics(ts) {
1196
+ return (nodeToReplace, node) => {
1197
+ if (!ts.isExpression(node)) return node;
1198
+ if (ts.isFunctionDeclaration(nodeToReplace)) {
1199
+ if (!nodeToReplace.name) return node;
1200
+ return ts.factory.createVariableStatement(
1201
+ nodeToReplace.modifiers,
1202
+ ts.factory.createVariableDeclarationList(
1203
+ [ts.factory.createVariableDeclaration(
1204
+ nodeToReplace.name,
1205
+ void 0,
1206
+ void 0,
1207
+ node
1208
+ )],
1209
+ ts.NodeFlags.Const
1210
+ )
1211
+ );
1212
+ } else if (ts.isMethodDeclaration(nodeToReplace)) {
1213
+ return ts.factory.createPropertyDeclaration(
1214
+ nodeToReplace.modifiers,
1215
+ nodeToReplace.name,
1216
+ void 0,
1217
+ void 0,
1218
+ node
1219
+ );
1220
+ }
1221
+ return node;
1222
+ };
1223
+ }
1281
1224
 
1282
1225
  // src/utils/TypeCheckerApi.ts
1283
1226
  function getMissingTypeEntriesInTargetType(ts, typeChecker) {
@@ -1299,6 +1242,110 @@ function getMissingTypeEntriesInTargetType(ts, typeChecker) {
1299
1242
  return result;
1300
1243
  };
1301
1244
  }
1245
+ function getInferredReturnType(ts, typeChecker) {
1246
+ function isConvertibleDeclaration(node) {
1247
+ switch (node.kind) {
1248
+ case ts.SyntaxKind.FunctionDeclaration:
1249
+ case ts.SyntaxKind.FunctionExpression:
1250
+ case ts.SyntaxKind.ArrowFunction:
1251
+ case ts.SyntaxKind.MethodDeclaration:
1252
+ return true;
1253
+ default:
1254
+ return false;
1255
+ }
1256
+ }
1257
+ return (node) => {
1258
+ let declaration = node;
1259
+ while (declaration && !isConvertibleDeclaration(declaration)) {
1260
+ declaration = declaration.parent;
1261
+ }
1262
+ if (!isConvertibleDeclaration(declaration)) return none2();
1263
+ if (!declaration || !declaration.body) {
1264
+ return none2();
1265
+ }
1266
+ let returnType;
1267
+ if (typeChecker.isImplementationOfOverload(declaration)) {
1268
+ const signatures = typeChecker.getTypeAtLocation(declaration).getCallSignatures();
1269
+ if (signatures.length > 1) {
1270
+ returnType = typeChecker.getUnionType(
1271
+ signatures.map((s) => s.getReturnType()).filter((_) => !!_)
1272
+ );
1273
+ }
1274
+ }
1275
+ if (!returnType) {
1276
+ const signature = typeChecker.getSignatureFromDeclaration(declaration);
1277
+ if (signature) {
1278
+ const typePredicate = typeChecker.getTypePredicateOfSignature(signature);
1279
+ if (typePredicate && typePredicate.type) {
1280
+ return some2(typePredicate.type);
1281
+ } else {
1282
+ returnType = typeChecker.getReturnTypeOfSignature(signature);
1283
+ }
1284
+ }
1285
+ }
1286
+ if (!returnType) {
1287
+ return none2();
1288
+ }
1289
+ return some2(returnType);
1290
+ };
1291
+ }
1292
+ function expectedAndRealType(ts, typeChecker) {
1293
+ return (node) => {
1294
+ if (ts.isVariableDeclaration(node) && node.initializer) {
1295
+ const expectedType = typeChecker.getTypeAtLocation(node.name);
1296
+ const realType = typeChecker.getTypeAtLocation(node.initializer);
1297
+ return [[node.name, expectedType, node.initializer, realType]];
1298
+ }
1299
+ if (ts.isCallExpression(node)) {
1300
+ const resolvedSignature = typeChecker.getResolvedSignature(node);
1301
+ if (resolvedSignature) {
1302
+ return resolvedSignature.getParameters().map((parameter, index) => {
1303
+ const expectedType = typeChecker.getTypeOfSymbolAtLocation(parameter, node);
1304
+ const realType = typeChecker.getTypeAtLocation(node.arguments[index]);
1305
+ return [node.arguments[index], expectedType, node.arguments[index], realType];
1306
+ });
1307
+ }
1308
+ }
1309
+ if (ts.isIdentifier(node) || ts.isStringLiteral(node) || ts.isNumericLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) {
1310
+ const parent = node.parent;
1311
+ if (ts.isObjectLiteralElement(parent)) {
1312
+ if (ts.isObjectLiteralExpression(parent.parent) && parent.name === node) {
1313
+ const type = typeChecker.getContextualType(parent.parent);
1314
+ if (type) {
1315
+ const symbol3 = typeChecker.getPropertyOfType(type, node.text);
1316
+ if (symbol3) {
1317
+ const expectedType = typeChecker.getTypeOfSymbolAtLocation(symbol3, node);
1318
+ const realType = typeChecker.getTypeAtLocation(node);
1319
+ return [[node, expectedType, node, realType]];
1320
+ }
1321
+ }
1322
+ }
1323
+ }
1324
+ }
1325
+ if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
1326
+ const expectedType = typeChecker.getTypeAtLocation(node.left);
1327
+ const realType = typeChecker.getTypeAtLocation(node.right);
1328
+ return [[node.left, expectedType, node.right, realType]];
1329
+ }
1330
+ if (ts.isReturnStatement(node) && node.expression) {
1331
+ const expectedType = getOrUndefined(getInferredReturnType(ts, typeChecker)(node));
1332
+ const realType = typeChecker.getTypeAtLocation(node.expression);
1333
+ if (expectedType) return [[node, expectedType, node, realType]];
1334
+ }
1335
+ if (ts.isArrowFunction(node) && ts.isExpression(node.body)) {
1336
+ const body = node.body;
1337
+ const expectedType = typeChecker.getContextualType(body);
1338
+ const realType = typeChecker.getTypeAtLocation(body);
1339
+ if (expectedType) return [[body, expectedType, body, realType]];
1340
+ }
1341
+ if (ts.isSatisfiesExpression(node)) {
1342
+ const expectedType = typeChecker.getTypeAtLocation(node.type);
1343
+ const realType = typeChecker.getTypeAtLocation(node.expression);
1344
+ return [[node.expression, expectedType, node.expression, realType]];
1345
+ }
1346
+ return [];
1347
+ };
1348
+ }
1302
1349
 
1303
1350
  // src/diagnostics/missingEffectContext.ts
1304
1351
  var missingEffectContext = createDiagnostic({
@@ -1544,7 +1591,9 @@ var asyncAwaitToGen = createRefactor({
1544
1591
  description: "Convert to Effect.gen",
1545
1592
  apply: (ts, program) => (sourceFile, textRange) => pipe(
1546
1593
  getNodesContainingRange(ts)(sourceFile, textRange),
1547
- filter(ts.isFunctionDeclaration),
1594
+ filter(
1595
+ (node) => ts.isFunctionDeclaration(node) || ts.isArrowFunction(node) || ts.isFunctionExpression(node)
1596
+ ),
1548
1597
  filter((node) => !!node.body),
1549
1598
  filter(
1550
1599
  (node) => !!(ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Async)
@@ -1554,15 +1603,25 @@ var asyncAwaitToGen = createRefactor({
1554
1603
  kind: "refactor.rewrite.effect.asyncAwaitToGen",
1555
1604
  description: "Rewrite to Effect.gen",
1556
1605
  apply: (changeTracker) => {
1557
- const effectName = getEffectModuleIdentifier(ts, program.getTypeChecker())(sourceFile);
1606
+ const isImportedEffectModule = importedEffectModule(
1607
+ ts,
1608
+ program.getTypeChecker()
1609
+ );
1610
+ const effectModuleIdentifierName = pipe(
1611
+ findImportedModuleIdentifier(ts)(
1612
+ (node2) => isSome2(isImportedEffectModule(node2))
1613
+ )(sourceFile),
1614
+ map((node2) => node2.text),
1615
+ getOrElse(() => "Effect")
1616
+ );
1558
1617
  const newDeclaration = transformAsyncAwaitToEffectGen(
1559
1618
  ts
1560
1619
  )(
1561
1620
  node,
1562
- effectName,
1621
+ effectModuleIdentifierName,
1563
1622
  (expression) => ts.factory.createCallExpression(
1564
1623
  ts.factory.createPropertyAccessExpression(
1565
- ts.factory.createIdentifier(effectName),
1624
+ ts.factory.createIdentifier(effectModuleIdentifierName),
1566
1625
  "promise"
1567
1626
  ),
1568
1627
  void 0,
@@ -1590,7 +1649,9 @@ var asyncAwaitToGenTryPromise = createRefactor({
1590
1649
  description: "Convert to Effect.gen with failures",
1591
1650
  apply: (ts, program) => (sourceFile, textRange) => pipe(
1592
1651
  getNodesContainingRange(ts)(sourceFile, textRange),
1593
- filter(ts.isFunctionDeclaration),
1652
+ filter(
1653
+ (node) => ts.isFunctionDeclaration(node) || ts.isArrowFunction(node) || ts.isFunctionExpression(node)
1654
+ ),
1594
1655
  filter((node) => !!node.body),
1595
1656
  filter(
1596
1657
  (node) => !!(ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Async)
@@ -1600,7 +1661,17 @@ var asyncAwaitToGenTryPromise = createRefactor({
1600
1661
  kind: "refactor.rewrite.effect.asyncAwaitToGenTryPromise",
1601
1662
  description: "Rewrite to Effect.gen with failures",
1602
1663
  apply: (changeTracker) => {
1603
- const effectName = getEffectModuleIdentifier(ts, program.getTypeChecker())(sourceFile);
1664
+ const isImportedEffectModule = importedEffectModule(
1665
+ ts,
1666
+ program.getTypeChecker()
1667
+ );
1668
+ const effectModuleIdentifierName = pipe(
1669
+ findImportedModuleIdentifier(ts)(
1670
+ (node2) => isSome2(isImportedEffectModule(node2))
1671
+ )(sourceFile),
1672
+ map((node2) => node2.text),
1673
+ getOrElse(() => "Effect")
1674
+ );
1604
1675
  let errorCount = 0;
1605
1676
  function createErrorADT() {
1606
1677
  errorCount++;
@@ -1619,10 +1690,10 @@ var asyncAwaitToGenTryPromise = createRefactor({
1619
1690
  ts
1620
1691
  )(
1621
1692
  node,
1622
- effectName,
1693
+ effectModuleIdentifierName,
1623
1694
  (expression) => ts.factory.createCallExpression(
1624
1695
  ts.factory.createPropertyAccessExpression(
1625
- ts.factory.createIdentifier(effectName),
1696
+ ts.factory.createIdentifier(effectModuleIdentifierName),
1626
1697
  "tryPromise"
1627
1698
  ),
1628
1699
  void 0,
@@ -1660,6 +1731,78 @@ var asyncAwaitToGenTryPromise = createRefactor({
1660
1731
  )
1661
1732
  });
1662
1733
 
1734
+ // src/refactors/effectGenToFn.ts
1735
+ var effectGenToFn = createRefactor({
1736
+ name: "effect/effectGenToFn",
1737
+ description: "Convert to Effect.fn",
1738
+ apply: (ts, program) => (sourceFile, textRange) => pipe(
1739
+ getNodesContainingRange(ts)(sourceFile, textRange),
1740
+ findFirst2(
1741
+ (node) => gen(function* () {
1742
+ const effectGen2 = yield* effectGen(ts, program.getTypeChecker())(node);
1743
+ let pipeArgs = ts.factory.createNodeArray([]);
1744
+ let nodeToReplace = node.parent;
1745
+ if (ts.isPropertyAccessExpression(node.parent) && node.parent.name.text === "pipe" && ts.isCallExpression(node.parent.parent)) {
1746
+ pipeArgs = node.parent.parent.arguments;
1747
+ nodeToReplace = node.parent.parent.parent;
1748
+ }
1749
+ while (nodeToReplace) {
1750
+ if (ts.isArrowFunction(nodeToReplace) || ts.isFunctionDeclaration(nodeToReplace) || ts.isMethodDeclaration(nodeToReplace)) {
1751
+ return { ...effectGen2, pipeArgs, nodeToReplace };
1752
+ }
1753
+ if (ts.isConciseBody(nodeToReplace) || ts.isReturnStatement(nodeToReplace)) {
1754
+ nodeToReplace = nodeToReplace.parent;
1755
+ continue;
1756
+ }
1757
+ if (ts.isBlock(nodeToReplace) && nodeToReplace.statements.length === 1) {
1758
+ nodeToReplace = nodeToReplace.parent;
1759
+ continue;
1760
+ }
1761
+ break;
1762
+ }
1763
+ return yield* none2();
1764
+ })
1765
+ ),
1766
+ map(
1767
+ ({ effectModule, generatorFunction, nodeToReplace, pipeArgs }) => ({
1768
+ kind: "refactor.rewrite.effect.effectGenToFn",
1769
+ description: "Convert to Effect.fn",
1770
+ apply: (changeTracker) => {
1771
+ const effectFn = nodeToReplace.name && ts.isIdentifier(nodeToReplace.name) ? ts.factory.createCallExpression(
1772
+ ts.factory.createPropertyAccessExpression(
1773
+ effectModule,
1774
+ "fn"
1775
+ ),
1776
+ void 0,
1777
+ [ts.factory.createStringLiteral(nodeToReplace.name.text)]
1778
+ ) : ts.factory.createPropertyAccessExpression(
1779
+ effectModule,
1780
+ "fn"
1781
+ );
1782
+ const effectFnCallWithGenerator = ts.factory.createCallExpression(
1783
+ effectFn,
1784
+ void 0,
1785
+ [ts.factory.createFunctionExpression(
1786
+ void 0,
1787
+ ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
1788
+ void 0,
1789
+ nodeToReplace.typeParameters,
1790
+ nodeToReplace.parameters,
1791
+ nodeToReplace.type,
1792
+ generatorFunction.body
1793
+ )].concat(pipeArgs)
1794
+ );
1795
+ changeTracker.replaceNode(
1796
+ sourceFile,
1797
+ nodeToReplace,
1798
+ tryPreserveDeclarationSemantics(ts)(nodeToReplace, effectFnCallWithGenerator)
1799
+ );
1800
+ }
1801
+ })
1802
+ )
1803
+ )
1804
+ });
1805
+
1663
1806
  // src/refactors/functionToArrow.ts
1664
1807
  var functionToArrow = createRefactor({
1665
1808
  name: "effect/functionToArrow",
@@ -1829,47 +1972,38 @@ var toggleReturnTypeAnnotation = createRefactor({
1829
1972
  name: "effect/toggleReturnTypeAnnotation",
1830
1973
  description: "Toggle return type annotation",
1831
1974
  apply: (ts, program) => (sourceFile, textRange) => {
1832
- function isConvertibleDeclaration(node) {
1833
- switch (node.kind) {
1834
- case ts.SyntaxKind.FunctionDeclaration:
1835
- case ts.SyntaxKind.FunctionExpression:
1836
- case ts.SyntaxKind.ArrowFunction:
1837
- case ts.SyntaxKind.MethodDeclaration:
1838
- return true;
1839
- default:
1840
- return false;
1841
- }
1842
- }
1843
- return pipe(
1844
- getNodesContainingRange(ts)(sourceFile, textRange),
1845
- filter(isConvertibleDeclaration),
1846
- head,
1847
- map(
1848
- (node) => ({
1975
+ return gen(function* () {
1976
+ const typeChecker = program.getTypeChecker();
1977
+ const node = yield* pipe(
1978
+ getNodesContainingRange(ts)(sourceFile, textRange),
1979
+ filter(
1980
+ (node2) => ts.isFunctionDeclaration(node2) || ts.isFunctionExpression(node2) || ts.isArrowFunction(node2) || ts.isMethodDeclaration(node2)
1981
+ ),
1982
+ head
1983
+ );
1984
+ if (node.type) {
1985
+ return {
1849
1986
  kind: "refactor.rewrite.effect.toggleReturnTypeAnnotation",
1850
1987
  description: "Toggle return type annotation",
1851
- apply: (changeTracker) => {
1852
- const typeChecker = program.getTypeChecker();
1853
- if (node.type) {
1854
- removeReturnTypeAnnotation(ts, changeTracker)(sourceFile, node);
1855
- return;
1856
- }
1857
- const callableType = typeChecker.getTypeAtLocation(node);
1858
- const returnTypes = callableType.getCallSignatures().map((s) => s.getReturnType());
1859
- const returnTypeNodes = returnTypes.map(
1860
- (type) => typeChecker.typeToTypeNode(type, node, ts.NodeBuilderFlags.NoTruncation)
1861
- ).filter((node2) => !!node2);
1862
- if (returnTypeNodes.length === 0) return;
1863
- const returnTypeNode = returnTypeNodes.length === 1 ? returnTypeNodes[0] : ts.factory.createUnionTypeNode(returnTypeNodes);
1864
- addReturnTypeAnnotation(ts, changeTracker)(
1865
- sourceFile,
1866
- node,
1867
- simplifyTypeNode(ts)(returnTypeNode)
1868
- );
1869
- }
1870
- })
1871
- )
1872
- );
1988
+ apply: (changeTracker) => removeReturnTypeAnnotation(ts, changeTracker)(sourceFile, node)
1989
+ };
1990
+ }
1991
+ const returnType = yield* getInferredReturnType(ts, typeChecker)(node);
1992
+ const returnTypeNode = yield* fromNullable(
1993
+ typeChecker.typeToTypeNode(returnType, node, ts.NodeBuilderFlags.NoTruncation)
1994
+ );
1995
+ return {
1996
+ kind: "refactor.rewrite.effect.toggleReturnTypeAnnotation",
1997
+ description: "Toggle return type annotation",
1998
+ apply: (changeTracker) => {
1999
+ addReturnTypeAnnotation(ts, changeTracker)(
2000
+ sourceFile,
2001
+ node,
2002
+ simplifyTypeNode(ts)(returnTypeNode)
2003
+ );
2004
+ }
2005
+ };
2006
+ });
1873
2007
  }
1874
2008
  });
1875
2009
 
@@ -1953,7 +2087,8 @@ var refactors = {
1953
2087
  toggleLazyConst,
1954
2088
  toggleReturnTypeAnnotation,
1955
2089
  toggleTypeAnnotation,
1956
- wrapWithPipe
2090
+ wrapWithPipe,
2091
+ effectGenToFn
1957
2092
  };
1958
2093
 
1959
2094
  // src/index.ts