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