@effect/language-service 0.6.0 → 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 +216 -201
  2. package/index.js.map +1 -1
  3. package/package.json +1 -1
package/index.js CHANGED
@@ -866,63 +866,6 @@ function effectFnGen(ts, typeChecker) {
866
866
  };
867
867
  });
868
868
  }
869
- function expectedAndRealType(ts, typeChecker) {
870
- return (node) => {
871
- if (ts.isVariableDeclaration(node) && node.initializer) {
872
- const expectedType = typeChecker.getTypeAtLocation(node.name);
873
- const realType = typeChecker.getTypeAtLocation(node.initializer);
874
- return [[node.name, expectedType, node.initializer, realType]];
875
- }
876
- if (ts.isCallExpression(node)) {
877
- const resolvedSignature = typeChecker.getResolvedSignature(node);
878
- if (resolvedSignature) {
879
- return resolvedSignature.getParameters().map((parameter, index) => {
880
- const expectedType = typeChecker.getTypeOfSymbolAtLocation(parameter, node);
881
- const realType = typeChecker.getTypeAtLocation(node.arguments[index]);
882
- return [node.arguments[index], expectedType, node.arguments[index], realType];
883
- });
884
- }
885
- }
886
- if (ts.isIdentifier(node) || ts.isStringLiteral(node) || ts.isNumericLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) {
887
- const parent = node.parent;
888
- if (ts.isObjectLiteralElement(parent)) {
889
- if (ts.isObjectLiteralExpression(parent.parent) && parent.name === node) {
890
- const type = typeChecker.getContextualType(parent.parent);
891
- if (type) {
892
- const symbol3 = typeChecker.getPropertyOfType(type, node.text);
893
- if (symbol3) {
894
- const expectedType = typeChecker.getTypeOfSymbolAtLocation(symbol3, node);
895
- const realType = typeChecker.getTypeAtLocation(node);
896
- return [[node, expectedType, node, realType]];
897
- }
898
- }
899
- }
900
- }
901
- }
902
- if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
903
- const expectedType = typeChecker.getTypeAtLocation(node.left);
904
- const realType = typeChecker.getTypeAtLocation(node.right);
905
- return [[node.left, expectedType, node.right, realType]];
906
- }
907
- if (ts.isReturnStatement(node) && node.expression) {
908
- const expectedType = typeChecker.getContextualType(node.expression);
909
- const realType = typeChecker.getTypeAtLocation(node.expression);
910
- if (expectedType) return [[node, expectedType, node, realType]];
911
- }
912
- if (ts.isArrowFunction(node) && ts.isExpression(node.body)) {
913
- const body = node.body;
914
- const expectedType = typeChecker.getContextualType(body);
915
- const realType = typeChecker.getTypeAtLocation(body);
916
- if (expectedType) return [[body, expectedType, body, realType]];
917
- }
918
- if (ts.isSatisfiesExpression(node)) {
919
- const expectedType = typeChecker.getTypeAtLocation(node.type);
920
- const realType = typeChecker.getTypeAtLocation(node.expression);
921
- return [[node.expression, expectedType, node.expression, realType]];
922
- }
923
- return [];
924
- };
925
- }
926
869
 
927
870
  // src/diagnostics/floatingEffect.ts
928
871
  var floatingEffect = createDiagnostic({
@@ -1060,71 +1003,8 @@ function toTextRange(positionOrRange) {
1060
1003
  function isNodeInRange(textRange) {
1061
1004
  return (node) => node.pos <= textRange.pos && node.end >= textRange.end;
1062
1005
  }
1063
- function findModuleNamedBindings(ts) {
1064
- return (sourceFile, moduleName) => fromNullable(ts.forEachChild(sourceFile, (node) => {
1065
- if (!ts.isImportDeclaration(node)) return;
1066
- const moduleSpecifier = node.moduleSpecifier;
1067
- if (!ts.isStringLiteral(moduleSpecifier)) return;
1068
- if (moduleSpecifier.text !== moduleName) return;
1069
- const importClause = node.importClause;
1070
- if (!importClause) return;
1071
- const namedBindings = importClause.namedBindings;
1072
- if (!namedBindings) return;
1073
- return namedBindings;
1074
- }));
1075
- }
1076
- function findModuleNamespaceImportIdentifierName(ts) {
1077
- return (sourceFile, moduleName) => pipe(
1078
- findModuleNamedBindings(ts)(sourceFile, moduleName),
1079
- map(
1080
- (namedBindings) => {
1081
- if (!ts.isNamespaceImport(namedBindings)) return;
1082
- return namedBindings.name.text;
1083
- }
1084
- ),
1085
- flatMap(fromNullable)
1086
- );
1087
- }
1088
- function findModuleNamedImportIdentifierName(ts) {
1089
- return (sourceFile, moduleName, namedImport) => pipe(
1090
- findModuleNamedBindings(ts)(sourceFile, moduleName),
1091
- map((namedBindings) => {
1092
- if (!ts.isNamedImports(namedBindings)) return;
1093
- for (const importSpecifier of namedBindings.elements) {
1094
- if (importSpecifier.propertyName?.getText() === namedImport) {
1095
- return importSpecifier.name?.escapedText || importSpecifier.propertyName?.getText();
1096
- }
1097
- }
1098
- }),
1099
- flatMap(fromNullable)
1100
- );
1101
- }
1102
- function findModuleImportIdentifierNameViaTypeChecker(ts, typeChecker) {
1103
- return (sourceFile, importName) => {
1104
- return fromNullable(ts.forEachChild(sourceFile, (node) => {
1105
- if (!ts.isImportDeclaration(node)) return;
1106
- if (!node.importClause) return;
1107
- const namedBindings = node.importClause.namedBindings;
1108
- if (!namedBindings) return;
1109
- if (ts.isNamespaceImport(namedBindings)) {
1110
- const symbol3 = typeChecker.getTypeAtLocation(namedBindings).getSymbol();
1111
- if (!symbol3 || !symbol3.exports) return;
1112
- if (!symbol3.exports.has(importName)) return;
1113
- return namedBindings.name.escapedText;
1114
- }
1115
- if (ts.isNamedImports(namedBindings)) {
1116
- for (const importSpecifier of namedBindings.elements) {
1117
- const symbol3 = typeChecker.getTypeAtLocation(importSpecifier).getSymbol();
1118
- if (!symbol3 || !symbol3.exports) return;
1119
- if (!symbol3.exports.has(importName)) return;
1120
- return importSpecifier.name?.escapedText || importSpecifier.propertyName?.getText();
1121
- }
1122
- }
1123
- }));
1124
- };
1125
- }
1126
1006
  function transformAsyncAwaitToEffectGen(ts) {
1127
- return (node, effectName, onAwait) => {
1007
+ return (node, effectModuleName, onAwait) => {
1128
1008
  function visitor(_) {
1129
1009
  if (ts.isAwaitExpression(_)) {
1130
1010
  const expression = ts.visitEachChild(_.expression, visitor, ts.nullTransformationContext);
@@ -1148,7 +1028,7 @@ function transformAsyncAwaitToEffectGen(ts) {
1148
1028
  );
1149
1029
  const effectGenCallExp = ts.factory.createCallExpression(
1150
1030
  ts.factory.createPropertyAccessExpression(
1151
- ts.factory.createIdentifier(effectName),
1031
+ ts.factory.createIdentifier(effectModuleName),
1152
1032
  "gen"
1153
1033
  ),
1154
1034
  void 0,
@@ -1224,17 +1104,24 @@ function removeReturnTypeAnnotation(ts, changes) {
1224
1104
  }
1225
1105
  };
1226
1106
  }
1227
- function getEffectModuleIdentifier(ts, typeChecker) {
1228
- return (sourceFile) => pipe(
1229
- findModuleNamespaceImportIdentifierName(ts)(sourceFile, "effect/Effect"),
1230
- orElse(() => findModuleNamedImportIdentifierName(ts)(sourceFile, "effect", "Effect")),
1231
- orElse(
1232
- () => findModuleImportIdentifierNameViaTypeChecker(ts, typeChecker)(sourceFile, "Effect")
1233
- ),
1234
- getOrElse(
1235
- () => "Effect"
1236
- )
1237
- );
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
+ };
1238
1125
  }
1239
1126
  function simplifyTypeNode(ts) {
1240
1127
  function collectCallable(typeNode) {
@@ -1305,6 +1192,35 @@ function deterministicTypeOrder(ts, typeChecker) {
1305
1192
  return 0;
1306
1193
  });
1307
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
+ }
1308
1224
 
1309
1225
  // src/utils/TypeCheckerApi.ts
1310
1226
  function getMissingTypeEntriesInTargetType(ts, typeChecker) {
@@ -1326,6 +1242,110 @@ function getMissingTypeEntriesInTargetType(ts, typeChecker) {
1326
1242
  return result;
1327
1243
  };
1328
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
+ }
1329
1349
 
1330
1350
  // src/diagnostics/missingEffectContext.ts
1331
1351
  var missingEffectContext = createDiagnostic({
@@ -1583,15 +1603,25 @@ var asyncAwaitToGen = createRefactor({
1583
1603
  kind: "refactor.rewrite.effect.asyncAwaitToGen",
1584
1604
  description: "Rewrite to Effect.gen",
1585
1605
  apply: (changeTracker) => {
1586
- 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
+ );
1587
1617
  const newDeclaration = transformAsyncAwaitToEffectGen(
1588
1618
  ts
1589
1619
  )(
1590
1620
  node,
1591
- effectName,
1621
+ effectModuleIdentifierName,
1592
1622
  (expression) => ts.factory.createCallExpression(
1593
1623
  ts.factory.createPropertyAccessExpression(
1594
- ts.factory.createIdentifier(effectName),
1624
+ ts.factory.createIdentifier(effectModuleIdentifierName),
1595
1625
  "promise"
1596
1626
  ),
1597
1627
  void 0,
@@ -1631,7 +1661,17 @@ var asyncAwaitToGenTryPromise = createRefactor({
1631
1661
  kind: "refactor.rewrite.effect.asyncAwaitToGenTryPromise",
1632
1662
  description: "Rewrite to Effect.gen with failures",
1633
1663
  apply: (changeTracker) => {
1634
- 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
+ );
1635
1675
  let errorCount = 0;
1636
1676
  function createErrorADT() {
1637
1677
  errorCount++;
@@ -1650,10 +1690,10 @@ var asyncAwaitToGenTryPromise = createRefactor({
1650
1690
  ts
1651
1691
  )(
1652
1692
  node,
1653
- effectName,
1693
+ effectModuleIdentifierName,
1654
1694
  (expression) => ts.factory.createCallExpression(
1655
1695
  ts.factory.createPropertyAccessExpression(
1656
- ts.factory.createIdentifier(effectName),
1696
+ ts.factory.createIdentifier(effectModuleIdentifierName),
1657
1697
  "tryPromise"
1658
1698
  ),
1659
1699
  void 0,
@@ -1707,7 +1747,7 @@ var effectGenToFn = createRefactor({
1707
1747
  nodeToReplace = node.parent.parent.parent;
1708
1748
  }
1709
1749
  while (nodeToReplace) {
1710
- if (ts.isArrowFunction(nodeToReplace) || ts.isFunctionDeclaration(nodeToReplace)) {
1750
+ if (ts.isArrowFunction(nodeToReplace) || ts.isFunctionDeclaration(nodeToReplace) || ts.isMethodDeclaration(nodeToReplace)) {
1711
1751
  return { ...effectGen2, pipeArgs, nodeToReplace };
1712
1752
  }
1713
1753
  if (ts.isConciseBody(nodeToReplace) || ts.isReturnStatement(nodeToReplace)) {
@@ -1728,7 +1768,7 @@ var effectGenToFn = createRefactor({
1728
1768
  kind: "refactor.rewrite.effect.effectGenToFn",
1729
1769
  description: "Convert to Effect.fn",
1730
1770
  apply: (changeTracker) => {
1731
- const effectFn = nodeToReplace.name ? ts.factory.createCallExpression(
1771
+ const effectFn = nodeToReplace.name && ts.isIdentifier(nodeToReplace.name) ? ts.factory.createCallExpression(
1732
1772
  ts.factory.createPropertyAccessExpression(
1733
1773
  effectModule,
1734
1774
  "fn"
@@ -1752,27 +1792,11 @@ var effectGenToFn = createRefactor({
1752
1792
  generatorFunction.body
1753
1793
  )].concat(pipeArgs)
1754
1794
  );
1755
- if (!ts.isArrowFunction(nodeToReplace) && nodeToReplace.name) {
1756
- const variableDeclaration = ts.factory.createVariableStatement(
1757
- nodeToReplace.modifiers,
1758
- ts.factory.createVariableDeclarationList(
1759
- [ts.factory.createVariableDeclaration(
1760
- nodeToReplace.name,
1761
- void 0,
1762
- void 0,
1763
- effectFnCallWithGenerator
1764
- )],
1765
- ts.NodeFlags.Const
1766
- )
1767
- );
1768
- changeTracker.replaceNode(
1769
- sourceFile,
1770
- nodeToReplace,
1771
- variableDeclaration
1772
- );
1773
- } else {
1774
- changeTracker.replaceNode(sourceFile, nodeToReplace, effectFnCallWithGenerator);
1775
- }
1795
+ changeTracker.replaceNode(
1796
+ sourceFile,
1797
+ nodeToReplace,
1798
+ tryPreserveDeclarationSemantics(ts)(nodeToReplace, effectFnCallWithGenerator)
1799
+ );
1776
1800
  }
1777
1801
  })
1778
1802
  )
@@ -1948,47 +1972,38 @@ var toggleReturnTypeAnnotation = createRefactor({
1948
1972
  name: "effect/toggleReturnTypeAnnotation",
1949
1973
  description: "Toggle return type annotation",
1950
1974
  apply: (ts, program) => (sourceFile, textRange) => {
1951
- function isConvertibleDeclaration(node) {
1952
- switch (node.kind) {
1953
- case ts.SyntaxKind.FunctionDeclaration:
1954
- case ts.SyntaxKind.FunctionExpression:
1955
- case ts.SyntaxKind.ArrowFunction:
1956
- case ts.SyntaxKind.MethodDeclaration:
1957
- return true;
1958
- default:
1959
- return false;
1960
- }
1961
- }
1962
- return pipe(
1963
- getNodesContainingRange(ts)(sourceFile, textRange),
1964
- filter(isConvertibleDeclaration),
1965
- head,
1966
- map(
1967
- (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 {
1968
1986
  kind: "refactor.rewrite.effect.toggleReturnTypeAnnotation",
1969
1987
  description: "Toggle return type annotation",
1970
- apply: (changeTracker) => {
1971
- const typeChecker = program.getTypeChecker();
1972
- if (node.type) {
1973
- removeReturnTypeAnnotation(ts, changeTracker)(sourceFile, node);
1974
- return;
1975
- }
1976
- const callableType = typeChecker.getTypeAtLocation(node);
1977
- const returnTypes = callableType.getCallSignatures().map((s) => s.getReturnType());
1978
- const returnTypeNodes = returnTypes.map(
1979
- (type) => typeChecker.typeToTypeNode(type, node, ts.NodeBuilderFlags.NoTruncation)
1980
- ).filter((node2) => !!node2);
1981
- if (returnTypeNodes.length === 0) return;
1982
- const returnTypeNode = returnTypeNodes.length === 1 ? returnTypeNodes[0] : ts.factory.createUnionTypeNode(returnTypeNodes);
1983
- addReturnTypeAnnotation(ts, changeTracker)(
1984
- sourceFile,
1985
- node,
1986
- simplifyTypeNode(ts)(returnTypeNode)
1987
- );
1988
- }
1989
- })
1990
- )
1991
- );
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
+ });
1992
2007
  }
1993
2008
  });
1994
2009