@effect/language-service 0.68.0 → 0.69.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/README.md CHANGED
@@ -81,6 +81,7 @@ And you're done! You'll now be able to use a set of refactors and diagnostics th
81
81
  - Warn when using `Effect.fail` with the global `Error` type, recommending tagged errors
82
82
  - Warn when `Layer.mergeAll` contains layers with interdependencies (where one layer provides a service that another layer in the same call requires)
83
83
  - Suggest using `Effect.fn` for functions that return `Effect.gen` for better tracing and concise syntax
84
+ - Warn when `Effect.fn` or `Effect.fnUntraced` is used as an IIFE (Immediately Invoked Function Expression), suggesting `Effect.gen` instead
84
85
  - Suggest removing redundant identifier argument when it equals the tag value in `Schema.TaggedClass`, `Schema.TaggedError`, or `Schema.TaggedRequest`
85
86
  - Suggest using `Schema.is` instead of `instanceof` for Effect Schema types
86
87
 
package/cli.js CHANGED
@@ -30214,7 +30214,7 @@ var runMain3 = runMain2;
30214
30214
  // package.json
30215
30215
  var package_default = {
30216
30216
  name: "@effect/language-service",
30217
- version: "0.68.0",
30217
+ version: "0.69.1",
30218
30218
  packageManager: "pnpm@8.11.0",
30219
30219
  publishConfig: {
30220
30220
  access: "public",
@@ -36266,6 +36266,104 @@ ${versions.map((version) => `- found ${version} at ${resolvedPackages[packageNam
36266
36266
  })
36267
36267
  });
36268
36268
 
36269
+ // src/diagnostics/effectFnIife.ts
36270
+ var effectFnIife = createDiagnostic({
36271
+ name: "effectFnIife",
36272
+ code: 46,
36273
+ description: "Effect.fn or Effect.fnUntraced is called as an IIFE (Immediately Invoked Function Expression). Use Effect.gen instead.",
36274
+ severity: "warning",
36275
+ apply: fn2("effectFnIife.apply")(function* (sourceFile, report) {
36276
+ const ts = yield* service2(TypeScriptApi);
36277
+ const typeParser = yield* service2(TypeParser);
36278
+ const tsUtils = yield* service2(TypeScriptUtils);
36279
+ const sourceEffectModuleName = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
36280
+ sourceFile,
36281
+ "effect",
36282
+ "Effect"
36283
+ ) || "Effect";
36284
+ const nodeToVisit = [];
36285
+ const appendNodeToVisit = (node) => {
36286
+ nodeToVisit.push(node);
36287
+ return void 0;
36288
+ };
36289
+ ts.forEachChild(sourceFile, appendNodeToVisit);
36290
+ while (nodeToVisit.length > 0) {
36291
+ const node = nodeToVisit.shift();
36292
+ ts.forEachChild(node, appendNodeToVisit);
36293
+ if (!ts.isCallExpression(node)) continue;
36294
+ const innerCall = node.expression;
36295
+ if (!ts.isCallExpression(innerCall)) continue;
36296
+ const parsed = yield* pipe(
36297
+ typeParser.effectFnGen(innerCall),
36298
+ map34((result) => ({
36299
+ kind: "fn",
36300
+ effectModule: result.effectModule,
36301
+ generatorFunction: result.generatorFunction,
36302
+ pipeArguments: result.pipeArguments
36303
+ })),
36304
+ orElse15(
36305
+ () => pipe(
36306
+ typeParser.effectFnUntracedGen(innerCall),
36307
+ map34((result) => ({
36308
+ kind: "fnUntraced",
36309
+ effectModule: result.effectModule,
36310
+ generatorFunction: result.generatorFunction,
36311
+ pipeArguments: result.pipeArguments
36312
+ }))
36313
+ )
36314
+ ),
36315
+ orElse15(
36316
+ () => pipe(
36317
+ typeParser.effectFn(innerCall),
36318
+ map34((result) => ({
36319
+ kind: "fn",
36320
+ effectModule: result.effectModule,
36321
+ generatorFunction: void 0,
36322
+ pipeArguments: result.pipeArguments
36323
+ }))
36324
+ )
36325
+ ),
36326
+ option5
36327
+ );
36328
+ if (isNone2(parsed)) continue;
36329
+ const { effectModule, generatorFunction, kind, pipeArguments: pipeArguments2 } = parsed.value;
36330
+ const effectModuleName = ts.isIdentifier(effectModule) ? ts.idText(effectModule) : sourceEffectModuleName;
36331
+ const fixes = [];
36332
+ if (generatorFunction && generatorFunction.parameters.length === 0) {
36333
+ fixes.push({
36334
+ fixName: "effectFnIife_toEffectGen",
36335
+ description: "Convert to Effect.gen",
36336
+ apply: gen3(function* () {
36337
+ const changeTracker = yield* service2(ChangeTracker);
36338
+ const effectGenCall = ts.factory.createCallExpression(
36339
+ ts.factory.createPropertyAccessExpression(
36340
+ ts.factory.createIdentifier(effectModuleName),
36341
+ "gen"
36342
+ ),
36343
+ void 0,
36344
+ [generatorFunction]
36345
+ );
36346
+ let replacementNode = effectGenCall;
36347
+ if (pipeArguments2.length > 0) {
36348
+ replacementNode = ts.factory.createCallExpression(
36349
+ ts.factory.createPropertyAccessExpression(effectGenCall, "pipe"),
36350
+ void 0,
36351
+ [...pipeArguments2]
36352
+ );
36353
+ }
36354
+ changeTracker.replaceNode(sourceFile, node, replacementNode);
36355
+ })
36356
+ });
36357
+ }
36358
+ report({
36359
+ location: node,
36360
+ 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).`,
36361
+ fixes
36362
+ });
36363
+ }
36364
+ })
36365
+ });
36366
+
36269
36367
  // src/diagnostics/effectFnOpportunity.ts
36270
36368
  var effectFnOpportunity = createDiagnostic({
36271
36369
  name: "effectFnOpportunity",
@@ -36531,9 +36629,11 @@ var effectFnOpportunity = createDiagnostic({
36531
36629
  });
36532
36630
  }
36533
36631
  const pipeArgsSuffix = pipeArguments2.length > 0 ? ` Effect.fn also accepts the piped transformations as additional arguments.` : ``;
36632
+ const suggestConsultingQuickFixes = ` Your editor quickfixes or the "effect-language-service" cli can show you how to convert to Effect.fn or Effect.fnUntraced.`;
36633
+ const orFnUntraced = target.value.generatorFunction ? `, or Effect.fnUntraced` : ``;
36534
36634
  report({
36535
36635
  location: nameIdentifier ?? targetNode,
36536
- messageText: target.value.generatorFunction ? `This function could benefit from Effect.fn's automatic tracing and concise syntax, or Effect.fnUntraced to get just a more concise syntax.${pipeArgsSuffix}` : `This function could benefit from Effect.fn's automatic tracing and concise syntax.${pipeArgsSuffix}`,
36636
+ messageText: `This function could benefit from Effect.fn's automatic tracing and concise syntax${orFnUntraced}.${pipeArgsSuffix}${suggestConsultingQuickFixes}`,
36537
36637
  fixes
36538
36638
  });
36539
36639
  }
@@ -39533,6 +39633,7 @@ var diagnostics = [
39533
39633
  globalErrorInEffectFailure,
39534
39634
  layerMergeAllWithDependencies,
39535
39635
  effectMapVoid,
39636
+ effectFnIife,
39536
39637
  effectFnOpportunity,
39537
39638
  redundantSchemaTagIdentifier,
39538
39639
  schemaSyncInEffect,