@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/index.js CHANGED
@@ -9119,7 +9119,7 @@ Instead, use tagged errors or custom errors with a discriminator property to get
9119
9119
  var globalErrorInEffectFailure = createDiagnostic({
9120
9120
  name: "globalErrorInEffectFailure",
9121
9121
  code: 35,
9122
- description: "Warns when Effect.fail is called with the global Error type",
9122
+ description: "Warns when the global Error type is used in an Effect failure channel",
9123
9123
  severity: "warning",
9124
9124
  apply: fn("globalErrorInEffectFailure.apply")(function* (sourceFile, report) {
9125
9125
  const ts = yield* service(TypeScriptApi);
@@ -9134,27 +9134,35 @@ var globalErrorInEffectFailure = createDiagnostic({
9134
9134
  while (nodeToVisit.length > 0) {
9135
9135
  const node = nodeToVisit.shift();
9136
9136
  ts.forEachChild(node, appendNodeToVisit);
9137
- if (ts.isCallExpression(node)) {
9138
- yield* pipe(
9139
- typeParser.isNodeReferenceToEffectModuleApi("fail")(node.expression),
9140
- flatMap4(() => {
9141
- if (node.arguments.length > 0) {
9142
- const failArgument = node.arguments[0];
9143
- const argumentType = typeCheckerUtils.getTypeAtLocation(failArgument);
9144
- if (argumentType && typeCheckerUtils.isGlobalErrorType(argumentType)) {
9145
- return sync(
9146
- () => report({
9147
- location: node,
9148
- 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.`,
9149
- fixes: []
9150
- })
9151
- );
9137
+ if (ts.isNewExpression(node)) {
9138
+ const newExpressionType = typeCheckerUtils.getTypeAtLocation(node);
9139
+ if (!newExpressionType || !typeCheckerUtils.isGlobalErrorType(newExpressionType)) {
9140
+ continue;
9141
+ }
9142
+ let current = node.parent;
9143
+ while (current) {
9144
+ const currentType = typeCheckerUtils.getTypeAtLocation(current);
9145
+ if (currentType) {
9146
+ const effectTypeResult = yield* pipe(
9147
+ typeParser.effectType(currentType, current),
9148
+ option
9149
+ );
9150
+ if (effectTypeResult._tag === "Some") {
9151
+ const effectType = effectTypeResult.value;
9152
+ const failureMembers = typeCheckerUtils.unrollUnionMembers(effectType.E);
9153
+ const hasGlobalError = failureMembers.some((member) => typeCheckerUtils.isGlobalErrorType(member));
9154
+ if (hasGlobalError) {
9155
+ report({
9156
+ location: node,
9157
+ 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.`,
9158
+ fixes: []
9159
+ });
9152
9160
  }
9161
+ break;
9153
9162
  }
9154
- return void_;
9155
- }),
9156
- ignore
9157
- );
9163
+ }
9164
+ current = current.parent;
9165
+ }
9158
9166
  }
9159
9167
  }
9160
9168
  })
@@ -9743,9 +9751,29 @@ var missedPipeableOpportunity = createDiagnostic({
9743
9751
  transformations: flow2.transformations.slice(0, firstPipeableIndex)
9744
9752
  });
9745
9753
  const afterTransformations = flow2.transformations.slice(pipeableEndIndex);
9754
+ const getOriginalSubjectNode = () => {
9755
+ if (firstPipeableIndex === 0) {
9756
+ return flow2.subject.node;
9757
+ }
9758
+ let current = flow2.node;
9759
+ for (let i = flow2.transformations.length; i > firstPipeableIndex; i--) {
9760
+ const t = flow2.transformations[i - 1];
9761
+ if (t.kind === "call" && ts.isCallExpression(current) && current.arguments.length > 0) {
9762
+ current = current.arguments[0];
9763
+ } else {
9764
+ return void 0;
9765
+ }
9766
+ }
9767
+ return current;
9768
+ };
9769
+ const originalSubjectNode = getOriginalSubjectNode();
9770
+ const subjectText = originalSubjectNode ? sourceFile.text.slice(
9771
+ ts.getTokenPosOfNode(originalSubjectNode, sourceFile),
9772
+ originalSubjectNode.end
9773
+ ).trim() : "";
9746
9774
  report({
9747
9775
  location: flow2.node,
9748
- messageText: `Nested function calls can be converted to pipeable style for better readability.`,
9776
+ messageText: `Nested function calls can be converted to pipeable style for better readability; consider using ${subjectText}.pipe(...) instead.`,
9749
9777
  fixes: [{
9750
9778
  fixName: "missedPipeableOpportunity_fix",
9751
9779
  description: "Convert to pipe style",