@effect/language-service 0.68.0 → 0.69.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect/language-service",
3
- "version": "0.68.0",
3
+ "version": "0.69.0",
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
@@ -4851,6 +4851,104 @@ ${versions.map((version) => `- found ${version} at ${resolvedPackages[packageNam
4851
4851
  })
4852
4852
  });
4853
4853
 
4854
+ // src/diagnostics/effectFnIife.ts
4855
+ var effectFnIife = createDiagnostic({
4856
+ name: "effectFnIife",
4857
+ code: 46,
4858
+ description: "Effect.fn or Effect.fnUntraced is called as an IIFE (Immediately Invoked Function Expression). Use Effect.gen instead.",
4859
+ severity: "warning",
4860
+ apply: fn("effectFnIife.apply")(function* (sourceFile, report) {
4861
+ const ts = yield* service(TypeScriptApi);
4862
+ const typeParser = yield* service(TypeParser);
4863
+ const tsUtils = yield* service(TypeScriptUtils);
4864
+ const sourceEffectModuleName = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
4865
+ sourceFile,
4866
+ "effect",
4867
+ "Effect"
4868
+ ) || "Effect";
4869
+ const nodeToVisit = [];
4870
+ const appendNodeToVisit = (node) => {
4871
+ nodeToVisit.push(node);
4872
+ return void 0;
4873
+ };
4874
+ ts.forEachChild(sourceFile, appendNodeToVisit);
4875
+ while (nodeToVisit.length > 0) {
4876
+ const node = nodeToVisit.shift();
4877
+ ts.forEachChild(node, appendNodeToVisit);
4878
+ if (!ts.isCallExpression(node)) continue;
4879
+ const innerCall = node.expression;
4880
+ if (!ts.isCallExpression(innerCall)) continue;
4881
+ const parsed = yield* pipe(
4882
+ typeParser.effectFnGen(innerCall),
4883
+ map4((result) => ({
4884
+ kind: "fn",
4885
+ effectModule: result.effectModule,
4886
+ generatorFunction: result.generatorFunction,
4887
+ pipeArguments: result.pipeArguments
4888
+ })),
4889
+ orElse2(
4890
+ () => pipe(
4891
+ typeParser.effectFnUntracedGen(innerCall),
4892
+ map4((result) => ({
4893
+ kind: "fnUntraced",
4894
+ effectModule: result.effectModule,
4895
+ generatorFunction: result.generatorFunction,
4896
+ pipeArguments: result.pipeArguments
4897
+ }))
4898
+ )
4899
+ ),
4900
+ orElse2(
4901
+ () => pipe(
4902
+ typeParser.effectFn(innerCall),
4903
+ map4((result) => ({
4904
+ kind: "fn",
4905
+ effectModule: result.effectModule,
4906
+ generatorFunction: void 0,
4907
+ pipeArguments: result.pipeArguments
4908
+ }))
4909
+ )
4910
+ ),
4911
+ option
4912
+ );
4913
+ if (isNone2(parsed)) continue;
4914
+ const { effectModule, generatorFunction, kind, pipeArguments: pipeArguments2 } = parsed.value;
4915
+ const effectModuleName = ts.isIdentifier(effectModule) ? ts.idText(effectModule) : sourceEffectModuleName;
4916
+ const fixes = [];
4917
+ if (generatorFunction && generatorFunction.parameters.length === 0) {
4918
+ fixes.push({
4919
+ fixName: "effectFnIife_toEffectGen",
4920
+ description: "Convert to Effect.gen",
4921
+ apply: gen(function* () {
4922
+ const changeTracker = yield* service(ChangeTracker);
4923
+ const effectGenCall = ts.factory.createCallExpression(
4924
+ ts.factory.createPropertyAccessExpression(
4925
+ ts.factory.createIdentifier(effectModuleName),
4926
+ "gen"
4927
+ ),
4928
+ void 0,
4929
+ [generatorFunction]
4930
+ );
4931
+ let replacementNode = effectGenCall;
4932
+ if (pipeArguments2.length > 0) {
4933
+ replacementNode = ts.factory.createCallExpression(
4934
+ ts.factory.createPropertyAccessExpression(effectGenCall, "pipe"),
4935
+ void 0,
4936
+ [...pipeArguments2]
4937
+ );
4938
+ }
4939
+ changeTracker.replaceNode(sourceFile, node, replacementNode);
4940
+ })
4941
+ });
4942
+ }
4943
+ report({
4944
+ location: node,
4945
+ messageText: `${effectModuleName}.${kind} returns a reusable function that can take arguments, but here it's called immediately. Use Effect.gen instead (optionally with Effect.withSpan for tracing).`,
4946
+ fixes
4947
+ });
4948
+ }
4949
+ })
4950
+ });
4951
+
4854
4952
  // src/diagnostics/effectFnOpportunity.ts
4855
4953
  var effectFnOpportunity = createDiagnostic({
4856
4954
  name: "effectFnOpportunity",
@@ -9151,6 +9249,7 @@ var diagnostics = [
9151
9249
  globalErrorInEffectFailure,
9152
9250
  layerMergeAllWithDependencies,
9153
9251
  effectMapVoid,
9252
+ effectFnIife,
9154
9253
  effectFnOpportunity,
9155
9254
  redundantSchemaTagIdentifier,
9156
9255
  schemaSyncInEffect,