@effect/language-service 0.69.2 → 0.70.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.69.2",
3
+ "version": "0.70.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
@@ -5645,7 +5645,7 @@ Instead, use tagged errors or custom errors with a discriminator property to get
5645
5645
  var globalErrorInEffectFailure = createDiagnostic({
5646
5646
  name: "globalErrorInEffectFailure",
5647
5647
  code: 35,
5648
- description: "Warns when Effect.fail is called with the global Error type",
5648
+ description: "Warns when the global Error type is used in an Effect failure channel",
5649
5649
  severity: "warning",
5650
5650
  apply: fn("globalErrorInEffectFailure.apply")(function* (sourceFile, report) {
5651
5651
  const ts = yield* service(TypeScriptApi);
@@ -5660,27 +5660,35 @@ var globalErrorInEffectFailure = createDiagnostic({
5660
5660
  while (nodeToVisit.length > 0) {
5661
5661
  const node = nodeToVisit.shift();
5662
5662
  ts.forEachChild(node, appendNodeToVisit);
5663
- if (ts.isCallExpression(node)) {
5664
- yield* pipe(
5665
- typeParser.isNodeReferenceToEffectModuleApi("fail")(node.expression),
5666
- flatMap2(() => {
5667
- if (node.arguments.length > 0) {
5668
- const failArgument = node.arguments[0];
5669
- const argumentType = typeCheckerUtils.getTypeAtLocation(failArgument);
5670
- if (argumentType && typeCheckerUtils.isGlobalErrorType(argumentType)) {
5671
- return sync(
5672
- () => report({
5673
- location: node,
5674
- messageText: `Effect.fail is called with the global Error type. It's not recommended to use the global Error type in Effect failures as they can get merged together. Instead, use tagged errors or custom errors with a discriminator property to get properly type-checked errors.`,
5675
- fixes: []
5676
- })
5677
- );
5663
+ if (ts.isNewExpression(node)) {
5664
+ const newExpressionType = typeCheckerUtils.getTypeAtLocation(node);
5665
+ if (!newExpressionType || !typeCheckerUtils.isGlobalErrorType(newExpressionType)) {
5666
+ continue;
5667
+ }
5668
+ let current = node.parent;
5669
+ while (current) {
5670
+ const currentType = typeCheckerUtils.getTypeAtLocation(current);
5671
+ if (currentType) {
5672
+ const effectTypeResult = yield* pipe(
5673
+ typeParser.effectType(currentType, current),
5674
+ option
5675
+ );
5676
+ if (effectTypeResult._tag === "Some") {
5677
+ const effectType = effectTypeResult.value;
5678
+ const failureMembers = typeCheckerUtils.unrollUnionMembers(effectType.E);
5679
+ const hasGlobalError = failureMembers.some((member) => typeCheckerUtils.isGlobalErrorType(member));
5680
+ if (hasGlobalError) {
5681
+ report({
5682
+ location: node,
5683
+ messageText: `The global Error type is used in an Effect failure channel. It's not recommended to use the global Error type in Effect failures as they can get merged together. Instead, use tagged errors or custom errors with a discriminator property to get properly type-checked errors.`,
5684
+ fixes: []
5685
+ });
5678
5686
  }
5687
+ break;
5679
5688
  }
5680
- return void_;
5681
- }),
5682
- ignore
5683
- );
5689
+ }
5690
+ current = current.parent;
5691
+ }
5684
5692
  }
5685
5693
  }
5686
5694
  })
@@ -6269,9 +6277,29 @@ var missedPipeableOpportunity = createDiagnostic({
6269
6277
  transformations: flow2.transformations.slice(0, firstPipeableIndex)
6270
6278
  });
6271
6279
  const afterTransformations = flow2.transformations.slice(pipeableEndIndex);
6280
+ const getOriginalSubjectNode = () => {
6281
+ if (firstPipeableIndex === 0) {
6282
+ return flow2.subject.node;
6283
+ }
6284
+ let current = flow2.node;
6285
+ for (let i = flow2.transformations.length; i > firstPipeableIndex; i--) {
6286
+ const t = flow2.transformations[i - 1];
6287
+ if (t.kind === "call" && ts.isCallExpression(current) && current.arguments.length > 0) {
6288
+ current = current.arguments[0];
6289
+ } else {
6290
+ return void 0;
6291
+ }
6292
+ }
6293
+ return current;
6294
+ };
6295
+ const originalSubjectNode = getOriginalSubjectNode();
6296
+ const subjectText = originalSubjectNode ? sourceFile.text.slice(
6297
+ ts.getTokenPosOfNode(originalSubjectNode, sourceFile),
6298
+ originalSubjectNode.end
6299
+ ).trim() : "";
6272
6300
  report({
6273
6301
  location: flow2.node,
6274
- messageText: `Nested function calls can be converted to pipeable style for better readability.`,
6302
+ messageText: `Nested function calls can be converted to pipeable style for better readability; consider using ${subjectText}.pipe(...) instead.`,
6275
6303
  fixes: [{
6276
6304
  fixName: "missedPipeableOpportunity_fix",
6277
6305
  description: "Convert to pipe style",