@effect/language-service 0.84.2 → 0.84.3

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.
@@ -3481,6 +3481,14 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
3481
3481
  ),
3482
3482
  ([A, E, R]) => ({ A, E, R })
3483
3483
  );
3484
+ const streamVarianceStruct = (type, atLocation) => map4(
3485
+ all(
3486
+ varianceStructCovariantType(type, atLocation, "_A"),
3487
+ varianceStructCovariantType(type, atLocation, "_E"),
3488
+ varianceStructCovariantType(type, atLocation, "_R")
3489
+ ),
3490
+ ([A, E, R]) => ({ A, E, R })
3491
+ );
3484
3492
  const layerVarianceStruct = (type, atLocation) => map4(
3485
3493
  all(
3486
3494
  varianceStructContravariantType(type, atLocation, "_ROut"),
@@ -3527,6 +3535,21 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
3527
3535
  "TypeParser.strictEffectType",
3528
3536
  (type) => type
3529
3537
  );
3538
+ const streamType = cachedBy(
3539
+ fn("TypeParser.streamType")(function* (type, atLocation) {
3540
+ if (supportedEffect() === "v3") {
3541
+ return yield* effectType(type, atLocation);
3542
+ }
3543
+ const typeIdSymbol = typeChecker.getPropertyOfType(type, "~effect/Stream");
3544
+ if (!typeIdSymbol) {
3545
+ return yield* typeParserIssue("Type is not a stream", type, atLocation);
3546
+ }
3547
+ const typeIdType = typeChecker.getTypeOfSymbolAtLocation(typeIdSymbol, atLocation);
3548
+ return yield* streamVarianceStruct(typeIdType, atLocation);
3549
+ }),
3550
+ "TypeParser.streamType",
3551
+ (type) => type
3552
+ );
3530
3553
  const isEffectTypeSourceFile = cachedBy(
3531
3554
  fn("TypeParser.isEffectTypeSourceFile")(function* (sourceFile) {
3532
3555
  const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
@@ -5262,6 +5285,7 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
5262
5285
  isServiceMapTypeSourceFile,
5263
5286
  isNodeReferenceToServiceMapModuleApi,
5264
5287
  effectType,
5288
+ streamType,
5265
5289
  strictEffectType,
5266
5290
  layerType,
5267
5291
  fiberType,
@@ -5489,7 +5513,7 @@ var catchAllToMapError = createDiagnostic({
5489
5513
  const { failArg, failCall } = failCallInfo;
5490
5514
  report({
5491
5515
  location: transformation.callee,
5492
- messageText: `You can use Effect.mapError instead of Effect.${catchAllName} + Effect.fail to transform the error type.`,
5516
+ messageText: `\`Effect.mapError\` expresses the same error-type transformation more directly than \`Effect.${catchAllName}\` followed by \`Effect.fail\`.`,
5493
5517
  fixes: [{
5494
5518
  fixName: "catchAllToMapError_fix",
5495
5519
  description: "Replace with Effect.mapError",
@@ -5553,7 +5577,7 @@ var catchUnfailableEffect = createDiagnostic({
5553
5577
  if (E.flags & ts.TypeFlags.Never) {
5554
5578
  report({
5555
5579
  location: transformation.callee,
5556
- messageText: `Looks like the previous effect never fails, so probably this error handling will never be triggered.`,
5580
+ messageText: "The previous Effect does not fail, so this error-handling branch will never run.",
5557
5581
  fixes: []
5558
5582
  });
5559
5583
  }
@@ -5616,7 +5640,7 @@ var classSelfMismatch = createDiagnostic({
5616
5640
  if (actualName !== expectedName) {
5617
5641
  report({
5618
5642
  location: selfTypeNode,
5619
- messageText: `Self type parameter should be '${expectedName}'`,
5643
+ messageText: `The \`Self\` type parameter for this class should be \`${expectedName}\`.`,
5620
5644
  fixes: [{
5621
5645
  fixName: "classSelfMismatch_fix",
5622
5646
  description: `Replace '${actualName}' with '${expectedName}'`,
@@ -5806,7 +5830,7 @@ var deterministicKeys = createDiagnostic({
5806
5830
  if (actualIdentifier !== expectedKey) {
5807
5831
  report({
5808
5832
  location: keyStringLiteral,
5809
- messageText: `Key should be '${expectedKey}'`,
5833
+ messageText: `This key does not match the deterministic key for this declaration. The expected key is \`${expectedKey}\`.`,
5810
5834
  fixes: [{
5811
5835
  fixName: "deterministicKeys_fix",
5812
5836
  description: `Replace '${actualIdentifier}' with '${expectedKey}'`,
@@ -5845,9 +5869,8 @@ var duplicatePackage = createDiagnostic({
5845
5869
  const versions = Object.keys(resolvedPackages[packageName]);
5846
5870
  report({
5847
5871
  location: sourceFile.statements[0],
5848
- messageText: `Package ${packageName} is referenced multiple times with different versions (${versions.join(", ")}) and may cause unexpected type errors.
5849
- Cleanup your dependencies and your package lockfile to avoid multiple instances of this package and reload the project.
5850
- If this is intended set the LSP config "allowedDuplicatedPackages" to ${JSON.stringify(options.allowedDuplicatedPackages.concat([packageName]))}.
5872
+ messageText: `Multiple versions of package \`${packageName}\` were detected: ${versions.join(", ")}. Package duplication can change runtime identity and type equality across Effect modules.
5873
+ If this is intentional, set the LSP config \`allowedDuplicatedPackages\` to ${JSON.stringify(options.allowedDuplicatedPackages.concat([packageName]))}.
5851
5874
 
5852
5875
  ${versions.map((version) => `- found ${version} at ${resolvedPackages[packageName][version]}`).join("\n")}`,
5853
5876
  fixes: []
@@ -5955,7 +5978,7 @@ var effectFnIife = createDiagnostic({
5955
5978
  const traceExpressionText = traceExpression ? sourceFile.text.slice(traceExpression.pos, traceExpression.end) : void 0;
5956
5979
  report({
5957
5980
  location: node,
5958
- messageText: `${effectModuleName}.${kind} returns a reusable function that can take arguments, but here it's called immediately. Use Effect.gen instead${traceExpressionText ? ` with Effect.withSpan(${traceExpressionText}) piped in the end to mantain tracing spans` : ``}.`,
5981
+ messageText: `\`${effectModuleName}.${kind}\` returns a reusable function that can take arguments, but it is invoked immediately here. \`Effect.gen\` represents the immediate-use form for this pattern${traceExpressionText ? ` with \`Effect.withSpan(${traceExpressionText})\` piped at the end to maintain tracing spans` : ``}.`,
5959
5982
  fixes
5960
5983
  });
5961
5984
  }
@@ -6040,7 +6063,7 @@ var effectFnImplicitAny = createDiagnostic({
6040
6063
  const parameterName = getParameterName(ts, parameter.name);
6041
6064
  report({
6042
6065
  location: parameter.name,
6043
- messageText: `Parameter '${parameterName}' implicitly has an 'any' type in Effect.fn/Effect.fnUntraced. Add an explicit type annotation or provide a contextual function type.`,
6066
+ messageText: `Parameter \`${parameterName}\` implicitly has type \`any\` in \`Effect.fn\`, \`Effect.fnUntraced\`, or \`Effect.fnUntracedEager\`. No parameter type is available from an explicit annotation or contextual function type.`,
6044
6067
  fixes: []
6045
6068
  });
6046
6069
  }
@@ -6636,7 +6659,7 @@ var effectFnOpportunity = createDiagnostic({
6636
6659
  const expectedSignature = generateExpectedSignature();
6637
6660
  report({
6638
6661
  location: nameIdentifier ?? targetNode,
6639
- messageText: `Can be rewritten as a reusable function: ${expectedSignature}`,
6662
+ messageText: `This expression can be rewritten in the reusable function form \`${expectedSignature}\`.`,
6640
6663
  fixes
6641
6664
  });
6642
6665
  }
@@ -6848,7 +6871,7 @@ var effectMapVoid = createDiagnostic({
6848
6871
  if (isNone2(match2)) continue;
6849
6872
  report({
6850
6873
  location: node.expression,
6851
- messageText: "Effect.asVoid can be used instead to discard the success value",
6874
+ messageText: "This expression discards the success value through mapping. `Effect.asVoid` represents that form directly.",
6852
6875
  fixes: [{
6853
6876
  fixName: "effectMapVoid_fix",
6854
6877
  description: "Replace with Effect.asVoid",
@@ -6903,7 +6926,7 @@ var effectSucceedWithVoid = createDiagnostic({
6903
6926
  if (!tsUtils.isVoidExpression(argument)) continue;
6904
6927
  report({
6905
6928
  location: node,
6906
- messageText: "Effect.void can be used instead of Effect.succeed(undefined) or Effect.succeed(void 0)",
6929
+ messageText: "`Effect.void` represents the same outcome as `Effect.succeed(undefined)` or `Effect.succeed(void 0)`.",
6907
6930
  fixes: [{
6908
6931
  fixName: "effectSucceedWithVoid_fix",
6909
6932
  description: "Replace with Effect.void",
@@ -6965,7 +6988,7 @@ var extendsNativeError = createDiagnostic({
6965
6988
  if (isNativeError) {
6966
6989
  report({
6967
6990
  location: node.name ?? typeExpression,
6968
- messageText: "Avoid extending the native 'Error' class directly. Consider using a tagged error (e.g. Data.TaggedError) to maintain type safety in the Effect failure channel.",
6991
+ messageText: "This class extends the native `Error` type directly. Untagged native errors lose distinction in the Effect failure channel.",
6969
6992
  fixes: []
6970
6993
  });
6971
6994
  }
@@ -7010,7 +7033,12 @@ var floatingEffect = createDiagnostic({
7010
7033
  if (!isFloatingExpression(node)) continue;
7011
7034
  const type = typeCheckerUtils.getTypeAtLocation(node.expression);
7012
7035
  if (!type) continue;
7013
- const effect = yield* option(typeParser.effectType(type, node.expression));
7036
+ const effect = yield* option(
7037
+ pipe(
7038
+ typeParser.effectType(type, node.expression),
7039
+ orElse2(() => typeParser.streamType(type, node.expression))
7040
+ )
7041
+ );
7014
7042
  if (isSome2(effect)) {
7015
7043
  const allowedFloatingEffects = yield* pipe(
7016
7044
  typeParser.fiberType(type, node.expression),
@@ -7019,10 +7047,9 @@ var floatingEffect = createDiagnostic({
7019
7047
  );
7020
7048
  if (isNone2(allowedFloatingEffects)) {
7021
7049
  const isStrictEffect = yield* option(typeParser.strictEffectType(type, node.expression));
7022
- const name = isSome2(isStrictEffect) ? "Effect" : "Effect-able " + typeChecker.typeToString(type);
7023
7050
  report({
7024
7051
  location: node,
7025
- messageText: `${name} must be yielded or assigned to a variable.`,
7052
+ messageText: isSome2(isStrictEffect) ? "This Effect value is neither yielded nor used in an assignment." : `This Effect-able \`${typeChecker.typeToString(type)}\` value is neither yielded nor assigned to a variable.`,
7026
7053
  fixes: []
7027
7054
  });
7028
7055
  }
@@ -7117,7 +7144,7 @@ var makeGlobalConsoleApply = (checkInEffect) => fn(`globalConsole${checkInEffect
7117
7144
  if (inEffect !== checkInEffect) continue;
7118
7145
  report({
7119
7146
  location: node,
7120
- messageText: checkInEffect ? `Prefer using ${alternative} instead of console.${method} inside Effect generators.` : `Prefer using ${alternative} instead of console.${method}.`,
7147
+ messageText: checkInEffect ? `This Effect code uses \`console.${method}\`, logging in Effect code is represented through \`${alternative}\`.` : `This code uses \`console.${method}\`, the corresponding Effect logging API is \`${alternative}\`.`,
7121
7148
  fixes: []
7122
7149
  });
7123
7150
  }
@@ -7166,10 +7193,10 @@ var makeGlobalDateApply = (checkInEffect) => fn(`globalDate${checkInEffect ? "In
7166
7193
  let objectNode;
7167
7194
  if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.idText(node.expression.name) === "now") {
7168
7195
  objectNode = node.expression.expression;
7169
- messageText = checkInEffect ? "Prefer using Clock or DateTime from Effect instead of Date.now() inside Effect generators." : "Prefer using Clock or DateTime from Effect instead of Date.now().";
7196
+ messageText = checkInEffect ? "This Effect code uses `Date.now()`, time access in Effect code is represented through `Clock` from Effect." : "This code uses `Date.now()`, time access is represented through `Clock` from Effect.";
7170
7197
  } else if (ts.isNewExpression(node)) {
7171
7198
  objectNode = node.expression;
7172
- messageText = checkInEffect ? "Prefer using DateTime from Effect instead of new Date() inside Effect generators." : "Prefer using DateTime from Effect instead of new Date().";
7199
+ messageText = checkInEffect ? "This Effect code constructs `new Date()`, date values in Effect code are represented through `DateTime` from Effect." : "This code constructs `new Date()`, date values are represented through `DateTime` from Effect.";
7173
7200
  }
7174
7201
  if (!messageText || !objectNode) continue;
7175
7202
  const symbol3 = typeChecker.getSymbolAtLocation(objectNode);
@@ -7252,7 +7279,7 @@ var globalErrorInEffectCatch = createDiagnostic({
7252
7279
  );
7253
7280
  report({
7254
7281
  location: node.expression,
7255
- messageText: `The 'catch' callback in ${nodeText} returns global 'Error', which loses type safety as untagged errors merge together. Consider using a tagged error and optionally wrapping the original in a 'cause' property.`,
7282
+ messageText: `The \`catch\` callback in \`${nodeText}\` returns the global \`Error\` type. Untagged errors merge together in the Effect error channel and lose type-level distinction; a tagged error preserves that distinction and can wrap the original error in a \`cause\` property.`,
7256
7283
  fixes: []
7257
7284
  });
7258
7285
  }
@@ -7332,7 +7359,7 @@ var makeGlobalFetchApply = (checkInEffect) => fn(`globalFetch${checkInEffect ? "
7332
7359
  if (!fetchSymbol) return;
7333
7360
  const effectVersion = typeParser.supportedEffect();
7334
7361
  const packageName = effectVersion === "v3" ? "@effect/platform" : "effect/unstable/http";
7335
- const messageText = checkInEffect ? `Prefer using HttpClient from ${packageName} instead of the global 'fetch' function inside Effect generators.` : `Prefer using HttpClient from ${packageName} instead of the global 'fetch' function.`;
7362
+ const messageText = checkInEffect ? `This Effect code calls the global \`fetch\` function, HTTP requests in Effect code are represented through \`HttpClient\` from \`${packageName}\`.` : `This code uses the global \`fetch\` function, HTTP requests are represented through \`HttpClient\` from \`${packageName}\`.`;
7336
7363
  const nodeToVisit = [];
7337
7364
  const appendNodeToVisit = (node) => {
7338
7365
  nodeToVisit.push(node);
@@ -7405,7 +7432,7 @@ var makeGlobalRandomApply = (checkInEffect) => fn(`globalRandom${checkInEffect ?
7405
7432
  if (inEffect !== checkInEffect) continue;
7406
7433
  report({
7407
7434
  location: node,
7408
- messageText: checkInEffect ? "Prefer using the Random service from Effect instead of Math.random() inside Effect generators." : "Prefer using the Random service from Effect instead of Math.random().",
7435
+ messageText: checkInEffect ? "This Effect code uses `Math.random()`, randomness is represented through the Effect `Random` service." : "This code uses `Math.random()`, randomness is represented through the Effect `Random` service.",
7409
7436
  fixes: []
7410
7437
  });
7411
7438
  }
@@ -7436,12 +7463,12 @@ var globalRandom = createDiagnostic({
7436
7463
  // src/diagnostics/globalTimersInEffect.ts
7437
7464
  var timerAlternatives = {
7438
7465
  "setTimeout": {
7439
- inEffect: "Prefer using Effect.sleep or Schedule from Effect instead of setTimeout inside Effect generators.",
7440
- outsideEffect: "Prefer using Effect.sleep or Schedule from Effect instead of setTimeout."
7466
+ inEffect: "This Effect code uses `setTimeout`, the corresponding timer API in this context is `Effect.sleep or Schedule` from Effect.",
7467
+ outsideEffect: "This code uses `setTimeout`, the corresponding Effect timer API is `Effect.sleep or Schedule` from Effect."
7441
7468
  },
7442
7469
  "setInterval": {
7443
- inEffect: "Prefer using Schedule or Effect.repeat from Effect instead of setInterval inside Effect generators.",
7444
- outsideEffect: "Prefer using Schedule or Effect.repeat from Effect instead of setInterval."
7470
+ inEffect: "This Effect code uses `setInterval`, the corresponding timer API in this context is `Schedule or Effect.repeat` from Effect.",
7471
+ outsideEffect: "This code uses `setInterval`, the corresponding Effect timer API is `Schedule or Effect.repeat` from Effect."
7445
7472
  }
7446
7473
  };
7447
7474
  var makeGlobalTimersApply = (checkInEffect) => fn(`globalTimers${checkInEffect ? "InEffect" : ""}.apply`)(function* (sourceFile, report) {
@@ -7683,7 +7710,7 @@ var instanceOfSchema = createDiagnostic({
7683
7710
  if (isSchemaType._tag === "Some") {
7684
7711
  report({
7685
7712
  location: node,
7686
- messageText: "Consider using Schema.is instead of instanceof for Effect Schema types.",
7713
+ messageText: "This code uses `instanceof` with an Effect Schema type. `Schema.is` is the schema-aware runtime check for this case.",
7687
7714
  fixes: [{
7688
7715
  fixName: "instanceOfSchema_fix",
7689
7716
  description: "Replace with Schema.is",
@@ -7953,7 +7980,7 @@ var leakingRequirements = createDiagnostic({
7953
7980
  location: node,
7954
7981
  messageText: `Methods of this Service require \`${requirementsStr}\` from every caller.
7955
7982
 
7956
- This leaks implementation details into the service's public type \u2014 callers shouldn't need to know *how* the service works internally, only *what* it provides.
7983
+ The requirement becomes part of the public service surface instead of remaining internal to Layer implementation.
7957
7984
 
7958
7985
  Resolve these dependencies at Layer creation and provide them to each method, so the service's type reflects its purpose, not its implementation.
7959
7986
 
@@ -8150,7 +8177,7 @@ var missedPipeableOpportunity = createDiagnostic({
8150
8177
  ).trim() : "";
8151
8178
  report({
8152
8179
  location: flow2.node,
8153
- messageText: `Nested function calls can be converted to pipeable style for better readability; consider using ${subjectText}.pipe(...) instead.`,
8180
+ messageText: `This nested call structure has a pipeable form. \`${subjectText}.pipe(...)\` represents the same call sequence in pipe style and may be easier to read.`,
8154
8181
  fixes: [{
8155
8182
  fixName: "missedPipeableOpportunity_fix",
8156
8183
  description: "Convert to pipe style",
@@ -8231,7 +8258,7 @@ var missingEffectContext = createDiagnostic({
8231
8258
  (missingTypes) => missingTypes.length > 0 ? report(
8232
8259
  {
8233
8260
  location: node,
8234
- messageText: `Missing '${sortTypes(missingTypes).map((_) => typeChecker.typeToString(_)).join(" | ")}' in the expected Effect context.`,
8261
+ messageText: `This Effect requires a service that is missing from the expected Effect context: \`${sortTypes(missingTypes).map((_) => typeChecker.typeToString(_)).join(" | ")}\`.`,
8235
8262
  fixes: []
8236
8263
  }
8237
8264
  ) : void 0
@@ -8582,7 +8609,7 @@ var missingReturnYieldStar = createDiagnostic({
8582
8609
  }];
8583
8610
  report({
8584
8611
  location: unwrapped,
8585
- messageText: `It is recommended to use return yield* for Effects that never succeed to signal a definitive exit point for type narrowing and tooling support.`,
8612
+ messageText: "This Effect never succeeds; using `return yield*` preserves a definitive generator exit point for type narrowing and tooling support.",
8586
8613
  fixes: fix
8587
8614
  });
8588
8615
  }
@@ -8638,7 +8665,7 @@ var missingStarInYieldEffectGen = createDiagnostic({
8638
8665
  brokenGenerators.forEach(
8639
8666
  (pos) => report({
8640
8667
  location: { pos, end: pos + "function".length },
8641
- messageText: `Seems like you used yield instead of yield* inside this Effect.gen.`,
8668
+ messageText: "This uses `yield` for an `Effect` value. `yield*` is the Effect-aware form in this context.",
8642
8669
  fixes: []
8643
8670
  })
8644
8671
  );
@@ -8660,7 +8687,7 @@ var missingStarInYieldEffectGen = createDiagnostic({
8660
8687
  }] : [];
8661
8688
  report({
8662
8689
  location: node,
8663
- messageText: `When yielding Effects inside Effect.gen, you should use yield* instead of yield.`,
8690
+ messageText: "This uses `yield` for an `Effect` value. `yield*` is the Effect-aware form in this context.",
8664
8691
  fixes: fix
8665
8692
  });
8666
8693
  });
@@ -8728,7 +8755,7 @@ var multipleEffectProvide = createDiagnostic({
8728
8755
  if (chunk.length < 2) continue;
8729
8756
  report({
8730
8757
  location: chunk[0].node,
8731
- messageText: "Avoid chaining Effect.provide calls, as this can lead to service lifecycle issues. Instead, merge layers and provide them in a single call.",
8758
+ messageText: "This expression chains multiple `Effect.provide` calls. Providing Layers in multiple calls in a chain can break service lifecycle behavior compared with a single combined provide with merged layers.",
8732
8759
  fixes: [{
8733
8760
  fixName: "multipleEffectProvide_fix",
8734
8761
  description: "Combine into a single provide",
@@ -8818,7 +8845,7 @@ var nodeBuiltinImport = createDiagnostic({
8818
8845
  if (match2) {
8819
8846
  report({
8820
8847
  location: statement.moduleSpecifier,
8821
- messageText: `Prefer using ${match2.alternative} from ${match2.package} instead of the Node.js '${match2.module}' module.`,
8848
+ messageText: `This module reference uses the \`${match2.module}\` module, the corresponding Effect API is \`${match2.alternative}\` from \`${match2.package}\`.`,
8822
8849
  fixes: []
8823
8850
  });
8824
8851
  }
@@ -8831,7 +8858,7 @@ var nodeBuiltinImport = createDiagnostic({
8831
8858
  if (match2) {
8832
8859
  report({
8833
8860
  location: arg,
8834
- messageText: `Prefer using ${match2.alternative} from ${match2.package} instead of the Node.js '${match2.module}' module.`,
8861
+ messageText: `This module reference uses the \`${match2.module}\` module, the corresponding Effect API is \`${match2.alternative}\` from \`${match2.package}\`.`,
8835
8862
  fixes: []
8836
8863
  });
8837
8864
  }
@@ -8885,7 +8912,7 @@ var nonObjectEffectServiceType = createDiagnostic({
8885
8912
  const propertyValue = property.initializer;
8886
8913
  const errorToReport = {
8887
8914
  location: property.name,
8888
- messageText: "Effect.Service requires the service type to be an object {} and not a primitive type. \nConsider wrapping the value in an object, or manually using Context.Tag or Effect.Tag if you want to use a primitive instead.",
8915
+ messageText: "`Effect.Service` is declared with a primitive service type. `Effect.Service` models object-shaped services; primitive values use `Context.Tag` or `Effect.Tag` directly.",
8889
8916
  fixes: []
8890
8917
  };
8891
8918
  if (propertyName === "succeed") {
@@ -9647,7 +9674,7 @@ var outdatedApi = createDiagnostic({
9647
9674
  hasReported = true;
9648
9675
  report({
9649
9676
  location: propertyAccess.name,
9650
- messageText: `${propertyName} is an Effect v3 API, but the project is using Effect v4.`,
9677
+ messageText: `This project targets Effect v4, but this code uses the Effect v3 API \`${propertyName}\`. The referenced API belongs to the v3 surface rather than the configured v4 surface.`,
9651
9678
  fixes: []
9652
9679
  });
9653
9680
  }
@@ -9690,7 +9717,7 @@ var outdatedApi = createDiagnostic({
9690
9717
  if (hasReported) {
9691
9718
  report({
9692
9719
  location: { pos: 0, end: 0 },
9693
- messageText: "This project targets Effect v4, but is using Effect v3 APIs. To find the correct API to use, clone and consult the github.com/effect-ts/effect-smol repository for the corresponding v4 replacement.",
9720
+ messageText: "This project targets Effect v4, but this code uses Effect v3 APIs. The referenced API belongs to the v3 surface rather than the configured v4 surface.",
9694
9721
  fixes: []
9695
9722
  });
9696
9723
  }
@@ -10935,7 +10962,7 @@ var overriddenSchemaConstructor = createDiagnostic({
10935
10962
  };
10936
10963
  report({
10937
10964
  location: member,
10938
- messageText: "Classes extending Schema must not override the constructor; this is because it silently breaks the schema decoding behaviour. If that's needed, we recommend instead to use a static 'new' method that constructs the instance.",
10965
+ messageText: "This Schema subclass defines its own constructor. For Schema classes, constructor overrides break decoding behavior for the class shape. Custom construction can be expressed through a static `new` method instead.",
10939
10966
  fixes: (member.body ? [fixAsStaticNew] : []).concat([{
10940
10967
  fixName: "overriddenSchemaConstructor_fix",
10941
10968
  description: "Remove the constructor override",
@@ -11057,7 +11084,7 @@ var preferSchemaOverJson = createDiagnostic({
11057
11084
  if (isSome2(match2)) {
11058
11085
  report({
11059
11086
  location: match2.value,
11060
- messageText: "Consider using Effect Schema for JSON operations instead of JSON.parse/JSON.stringify",
11087
+ messageText: "This code uses `JSON.parse` or `JSON.stringify`. Effect Schema provides Effect-aware APIs for JSON parsing and stringifying.",
11061
11088
  fixes: []
11062
11089
  });
11063
11090
  }
@@ -11175,9 +11202,7 @@ var returnEffectInGen = createDiagnostic({
11175
11202
  }] : [];
11176
11203
  report({
11177
11204
  location: node,
11178
- messageText: `You are returning an Effect-able type inside a generator function, and will result in nested Effect<Effect<...>>.
11179
- Maybe you wanted to return yield* instead?
11180
- Nested Effect-able types may be intended if you plan to later manually flatten or unwrap this Effect, if so you can safely disable this diagnostic for this line through quickfixes.`,
11205
+ messageText: "This generator returns an Effect-able value directly, which produces a nested `Effect<Effect<...>>`. If the intended result is the inner Effect value, `return yield*` represents that form.",
11181
11206
  fixes: fix
11182
11207
  });
11183
11208
  }),
@@ -11332,9 +11357,7 @@ var runEffectInsideEffect = createDiagnostic({
11332
11357
  );
11333
11358
  });
11334
11359
  const v4MethodName = `${isEffectRunCall.value.methodName}With`;
11335
- const messageText = supportedEffect === "v4" ? `Using ${nodeText} inside an Effect is not recommended. The same services should generally be used instead to run child effects.
11336
- Consider extracting the current services by using for example Effect.services and then use Effect.${v4MethodName} with the extracted services instead.` : `Using ${nodeText} inside an Effect is not recommended. The same runtime should generally be used instead to run child effects.
11337
- Consider extracting the Runtime by using for example Effect.runtime and then use Runtime.${isEffectRunCall.value.methodName} with the extracted runtime instead.`;
11360
+ const messageText = supportedEffect === "v4" ? `\`${nodeText}\` is called inside an Effect with a separate services invocation. In this context, child Effects run with the surrounding services, which can be accessed through \`Effect.services\` and \`Effect.${v4MethodName}\`.` : `\`${nodeText}\` is called inside an Effect with a separate runtime invocation. In this context, run child Effects with the surrounding runtime, which can be accessed through \`Effect.runtime\` and \`Runtime.${isEffectRunCall.value.methodName}\`.`;
11338
11361
  report({
11339
11362
  location: node.expression,
11340
11363
  messageText,
@@ -11347,7 +11370,7 @@ Consider extracting the Runtime by using for example Effect.runtime and then use
11347
11370
  } else {
11348
11371
  report({
11349
11372
  location: node.expression,
11350
- messageText: `Using ${nodeText} inside an Effect is not recommended. Effects inside generators can usually just be yielded.`,
11373
+ messageText: `\`${nodeText}\` is called inside an existing Effect context. Here, the inner Effect can be used directly.`,
11351
11374
  fixes: []
11352
11375
  });
11353
11376
  }
@@ -11402,7 +11425,7 @@ var schemaStructWithTag = createDiagnostic({
11402
11425
  const otherProperties = arg.properties.filter((prop) => prop !== tagProperty);
11403
11426
  report({
11404
11427
  location: node,
11405
- messageText: "Schema.Struct with a _tag field can be simplified to Schema.TaggedStruct to make the tag optional in the constructor.",
11428
+ messageText: "This `Schema.Struct` includes a `_tag` field. `Schema.TaggedStruct` is the tagged-struct form for this pattern and makes the tag optional in the constructor.",
11406
11429
  fixes: [{
11407
11430
  fixName: "schemaStructWithTag_fix",
11408
11431
  description: "Replace with Schema.TaggedStruct",
@@ -11495,7 +11518,7 @@ var schemaSyncInEffect = createDiagnostic({
11495
11518
  const effectMethodName = syncToEffectMethod[isSchemaSyncCall.value.methodName];
11496
11519
  report({
11497
11520
  location: node.expression,
11498
- messageText: `Using ${nodeText} inside an Effect generator is not recommended. Use Schema.${effectMethodName} instead to get properly typed error channel.`,
11521
+ messageText: `\`${nodeText}\` is used inside an Effect generator. \`Schema.${effectMethodName}\` preserves the typed Effect error channel for this operation without throwing.`,
11499
11522
  fixes: []
11500
11523
  });
11501
11524
  }
@@ -11555,7 +11578,7 @@ var schemaUnionOfLiterals = createDiagnostic({
11555
11578
  const schemaLiteralExpression = firstLiteralCall.expression;
11556
11579
  report({
11557
11580
  location: node,
11558
- messageText: "A Schema.Union of multiple Schema.Literal calls can be simplified to a single Schema.Literal call.",
11581
+ messageText: "This `Schema.Union` contains multiple `Schema.Literal` members and can be simplified to a single `Schema.Literal` call.",
11559
11582
  fixes: [{
11560
11583
  fixName: "schemaUnionOfLiterals_fix",
11561
11584
  description: "Replace with a single Schema.Literal call",
@@ -11618,8 +11641,7 @@ var scopeInLayerEffect = createDiagnostic({
11618
11641
  map4(
11619
11642
  () => report({
11620
11643
  location: node,
11621
- messageText: `Seems like you are constructing a layer with a scope in the requirements.
11622
- Consider using "scoped" instead to get rid of the scope in the requirements.`,
11644
+ messageText: "This layer construction leaves `Scope` in the requirement set. The scoped API removes `Scope` from the resulting requirements.",
11623
11645
  fixes: methodIdentifier ? [{
11624
11646
  fixName: "scopeInLayerEffect_scoped",
11625
11647
  description: "Use scoped for Layer creation",
@@ -11719,7 +11741,7 @@ var serviceNotAsClass = createDiagnostic({
11719
11741
  const shapeText = typeArgs.length > 0 ? typeArgs.map((t) => sourceFile.text.substring(ts.getTokenPosOfNode(t, sourceFile), t.end)).join(", ") : "Shape";
11720
11742
  report({
11721
11743
  location: callExpr,
11722
- messageText: `ServiceMap.Service should be used in a class declaration instead of as a variable. Use: class ${variableName} extends ServiceMap.Service<${variableName}, ${shapeText}>()("${argsText.replace(/['"]/g, "")}") {}`,
11744
+ messageText: `\`ServiceMap.Service\` is assigned to a variable here, but this API is intended for a class declaration shape such as \`class ${variableName} extends ServiceMap.Service<${variableName}, ${shapeText}>()("${argsText.replace(/['"]/g, "")}") {}\`.`,
11723
11745
  fixes: [{
11724
11746
  fixName: "serviceNotAsClass",
11725
11747
  description: `Convert to class declaration`,
@@ -11932,7 +11954,7 @@ var tryCatchInEffectGen = createDiagnostic({
11932
11954
  map4(() => {
11933
11955
  report({
11934
11956
  location: node,
11935
- messageText: `Avoid using try/catch inside Effect generators. Use Effect's error handling mechanisms instead (e.g. ${alternatives.join(", ")}).`,
11957
+ messageText: `This Effect generator contains \`try/catch\`; in this context, error handling is expressed with Effect APIs such as ${alternatives.join(", ")}).`,
11936
11958
  fixes: []
11937
11959
  });
11938
11960
  }),
@@ -11993,8 +12015,7 @@ var unknownInEffectCatch = createDiagnostic({
11993
12015
  );
11994
12016
  report({
11995
12017
  location: node.expression,
11996
- messageText: `The 'catch' callback in ${nodeText} returns 'unknown'. The catch callback should be used to provide typed errors.
11997
- Consider wrapping unknown errors into Effect's Data.TaggedError for example, or narrow down the type to the specific error raised.`,
12018
+ messageText: `The \`catch\` callback in \`${nodeText}\` returns \`unknown\`, so the Effect error type stays untyped. A specific typed error preserves error-channel information, for example by narrowing the value or wrapping it in \`Data.TaggedError\`.`,
11998
12019
  fixes: []
11999
12020
  });
12000
12021
  }
@@ -12091,7 +12112,7 @@ var unnecessaryFailYieldableError = createDiagnostic({
12091
12112
  map4(
12092
12113
  () => report({
12093
12114
  location: node,
12094
- messageText: `This Effect.fail call uses a yieldable error type as argument. You can yield* the error directly instead.`,
12115
+ messageText: "This `yield* Effect.fail(...)` passes a yieldable error value. `yield*` represents that value directly without wrapping it in `Effect.fail`.",
12095
12116
  fixes: [{
12096
12117
  fixName: "unnecessaryFailYieldableError_fix",
12097
12118
  description: "Replace yield* Effect.fail with yield*",
@@ -12196,7 +12217,7 @@ var unnecessaryPipeChain = createDiagnostic({
12196
12217
  map4(({ innerCall, pipeCall }) => {
12197
12218
  report({
12198
12219
  location: node,
12199
- messageText: `Chained pipe calls can be simplified to a single pipe call`,
12220
+ messageText: "This expression contains chained `pipe` calls that can be simplified to a single `pipe` call.",
12200
12221
  fixes: [{
12201
12222
  fixName: "unnecessaryPipeChain_fix",
12202
12223
  description: "Rewrite as single pipe call",