@effect/language-service 0.57.0 → 0.57.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect/language-service",
3
- "version": "0.57.0",
3
+ "version": "0.57.1",
4
4
  "description": "A Language-Service Plugin to Refactor and Diagnostic effect-ts projects",
5
5
  "main": "index.cjs",
6
6
  "bin": {
package/transform.js CHANGED
@@ -5897,6 +5897,11 @@ var runEffectInsideEffect = createDiagnostic({
5897
5897
  apply: fn("runEffectInsideEffect.apply")(function* (sourceFile, report) {
5898
5898
  const ts = yield* service(TypeScriptApi);
5899
5899
  const typeParser = yield* service(TypeParser);
5900
+ const tsUtils = yield* service(TypeScriptUtils);
5901
+ const parseEffectMethod = (node, methodName) => pipe(
5902
+ typeParser.isNodeReferenceToEffectModuleApi(methodName)(node),
5903
+ map4(() => ({ node, methodName }))
5904
+ );
5900
5905
  const nodeToVisit = [];
5901
5906
  const appendNodeToVisit = (node) => {
5902
5907
  nodeToVisit.push(node);
@@ -5907,11 +5912,12 @@ var runEffectInsideEffect = createDiagnostic({
5907
5912
  const node = nodeToVisit.shift();
5908
5913
  ts.forEachChild(node, appendNodeToVisit);
5909
5914
  if (!ts.isCallExpression(node)) continue;
5915
+ if (node.arguments.length === 0) continue;
5910
5916
  const isEffectRunCall = yield* pipe(
5911
- typeParser.isNodeReferenceToEffectModuleApi("runPromise")(node.expression),
5912
- orElse2(() => typeParser.isNodeReferenceToEffectModuleApi("runSync")(node.expression)),
5913
- orElse2(() => typeParser.isNodeReferenceToEffectModuleApi("runFork")(node.expression)),
5914
- orElse2(() => typeParser.isNodeReferenceToEffectModuleApi("runCallback")(node.expression)),
5917
+ parseEffectMethod(node.expression, "runPromise"),
5918
+ orElse2(() => parseEffectMethod(node.expression, "runSync")),
5919
+ orElse2(() => parseEffectMethod(node.expression, "runFork")),
5920
+ orElse2(() => parseEffectMethod(node.expression, "runCallback")),
5915
5921
  option
5916
5922
  );
5917
5923
  if (isNone2(isEffectRunCall)) continue;
@@ -5931,18 +5937,90 @@ var runEffectInsideEffect = createDiagnostic({
5931
5937
  orElse2(() => typeParser.effectFnGen(possiblyEffectGen)),
5932
5938
  option
5933
5939
  );
5934
- if (isSome2(isInEffectGen)) {
5940
+ if (isSome2(isInEffectGen) && isInEffectGen.value.body.statements.length > 0) {
5935
5941
  const nodeText = sourceFile.text.substring(
5936
5942
  ts.getTokenPosOfNode(node.expression, sourceFile),
5937
5943
  node.expression.end
5938
5944
  );
5939
- const messageText = nodeIntroduceScope && nodeIntroduceScope !== isInEffectGen.value.generatorFunction ? `Using ${nodeText} inside an Effect is not recommended. The same runtime should generally be used instead to run child effects.
5940
- Consider extracting the Runtime by using for example Effect.runtime and then use Runtime.run* with the extracted runtime instead.` : `Using ${nodeText} inside an Effect is not recommended. Effects inside generators can usually just be yielded.`;
5941
- report({
5942
- location: node.expression,
5943
- messageText,
5944
- fixes: []
5945
- });
5945
+ if (nodeIntroduceScope && nodeIntroduceScope !== isInEffectGen.value.generatorFunction) {
5946
+ const fixAddRuntime = gen(function* () {
5947
+ const changeTracker = yield* service(ChangeTracker);
5948
+ const runtimeModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, "effect", "Runtime") || "Runtime";
5949
+ const effectModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, "effect", "Effect") || "Effect";
5950
+ let runtimeIdentifier = void 0;
5951
+ for (const statement of isInEffectGen.value.generatorFunction.body.statements) {
5952
+ if (ts.isVariableStatement(statement) && statement.declarationList.declarations.length === 1) {
5953
+ const declaration = statement.declarationList.declarations[0];
5954
+ if (declaration.initializer && ts.isYieldExpression(declaration.initializer) && declaration.initializer.asteriskToken && declaration.initializer.expression) {
5955
+ const yieldedExpression = declaration.initializer.expression;
5956
+ if (ts.isCallExpression(yieldedExpression)) {
5957
+ const maybeEffectRuntime = yield* pipe(
5958
+ typeParser.isNodeReferenceToEffectModuleApi("runtime")(yieldedExpression.expression),
5959
+ option
5960
+ );
5961
+ if (isSome2(maybeEffectRuntime) && ts.isIdentifier(declaration.name)) {
5962
+ runtimeIdentifier = ts.idText(declaration.name);
5963
+ }
5964
+ }
5965
+ }
5966
+ }
5967
+ }
5968
+ if (!runtimeIdentifier) {
5969
+ changeTracker.insertNodeAt(
5970
+ sourceFile,
5971
+ isInEffectGen.value.body.statements[0].pos,
5972
+ ts.factory.createVariableStatement(
5973
+ void 0,
5974
+ ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(
5975
+ "effectRuntime",
5976
+ void 0,
5977
+ void 0,
5978
+ ts.factory.createYieldExpression(
5979
+ ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
5980
+ ts.factory.createCallExpression(
5981
+ ts.factory.createPropertyAccessExpression(
5982
+ ts.factory.createIdentifier(effectModuleIdentifier),
5983
+ "runtime"
5984
+ ),
5985
+ [ts.factory.createTypeReferenceNode("never")],
5986
+ []
5987
+ )
5988
+ )
5989
+ )], ts.NodeFlags.Const)
5990
+ ),
5991
+ {
5992
+ prefix: "\n",
5993
+ suffix: "\n"
5994
+ }
5995
+ );
5996
+ }
5997
+ changeTracker.deleteRange(sourceFile, {
5998
+ pos: ts.getTokenPosOfNode(node.expression, sourceFile),
5999
+ end: node.arguments[0].pos
6000
+ });
6001
+ changeTracker.insertText(
6002
+ sourceFile,
6003
+ node.arguments[0].pos,
6004
+ `${runtimeModuleIdentifier}.${isEffectRunCall.value.methodName}(${runtimeIdentifier || "effectRuntime"}, `
6005
+ );
6006
+ });
6007
+ report({
6008
+ location: node.expression,
6009
+ messageText: `Using ${nodeText} inside an Effect is not recommended. The same runtime should generally be used instead to run child effects.
6010
+ Consider extracting the Runtime by using for example Effect.runtime and then use Runtime.${isEffectRunCall.value.methodName} with the extracted runtime instead.`,
6011
+ fixes: [{
6012
+ fixName: "runEffectInsideEffect_fix",
6013
+ description: "Use a runtime to run the Effect",
6014
+ apply: fixAddRuntime
6015
+ }]
6016
+ });
6017
+ } else {
6018
+ report({
6019
+ location: node.expression,
6020
+ messageText: `Using ${nodeText} inside an Effect is not recommended. Effects inside generators can usually just be yielded.`,
6021
+ fixes: []
6022
+ });
6023
+ }
5946
6024
  }
5947
6025
  currentParent = currentParent.parent;
5948
6026
  }