@effect/language-service 0.84.1 → 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.
@@ -3122,10 +3122,42 @@ function makeTypeCheckerUtils(ts, typeChecker, tsUtils) {
3122
3122
  if (node.parent && ts.isJsxOpeningElement(node.parent) && node.parent.tagName === node) return;
3123
3123
  if (node.parent && ts.isJsxClosingElement(node.parent) && node.parent.tagName === node) return;
3124
3124
  if (node.parent && ts.isJsxAttribute(node.parent) && node.parent.name === node) return;
3125
+ if (isInsideTypeOnlyHeritageExpression(node)) return;
3125
3126
  if (ts.isExpression(node) || ts.isTypeNode(node)) {
3126
3127
  return typeChecker.getTypeAtLocation(node);
3127
3128
  }
3128
3129
  }
3130
+ function isInsideTypeOnlyHeritageExpression(node) {
3131
+ if (ts.isExpressionWithTypeArguments(node)) {
3132
+ return isTypeOnlyHeritageClause(node.parent);
3133
+ }
3134
+ if (!ts.isIdentifier(node) && !ts.isPropertyAccessExpression(node)) {
3135
+ return false;
3136
+ }
3137
+ for (let current = node.parent; current; current = current.parent) {
3138
+ if (ts.isPropertyAccessExpression(current)) {
3139
+ continue;
3140
+ }
3141
+ if (ts.isExpressionWithTypeArguments(current)) {
3142
+ return isTypeOnlyHeritageClause(current.parent);
3143
+ }
3144
+ return false;
3145
+ }
3146
+ return false;
3147
+ }
3148
+ function isTypeOnlyHeritageClause(node) {
3149
+ if (!node || !ts.isHeritageClause(node)) {
3150
+ return false;
3151
+ }
3152
+ const container = node.parent;
3153
+ if (!container) {
3154
+ return false;
3155
+ }
3156
+ if (ts.isInterfaceDeclaration(container)) {
3157
+ return true;
3158
+ }
3159
+ return ts.isClassLike(container) && node.token === ts.SyntaxKind.ImplementsKeyword;
3160
+ }
3129
3161
  function resolveToGlobalSymbol(symbol3) {
3130
3162
  if (symbol3.flags & ts.SymbolFlags.Alias) {
3131
3163
  symbol3 = typeChecker.getAliasedSymbol(symbol3);
@@ -3449,6 +3481,14 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
3449
3481
  ),
3450
3482
  ([A, E, R]) => ({ A, E, R })
3451
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
+ );
3452
3492
  const layerVarianceStruct = (type, atLocation) => map4(
3453
3493
  all(
3454
3494
  varianceStructContravariantType(type, atLocation, "_ROut"),
@@ -3495,6 +3535,21 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
3495
3535
  "TypeParser.strictEffectType",
3496
3536
  (type) => type
3497
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
+ );
3498
3553
  const isEffectTypeSourceFile = cachedBy(
3499
3554
  fn("TypeParser.isEffectTypeSourceFile")(function* (sourceFile) {
3500
3555
  const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
@@ -5230,6 +5285,7 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
5230
5285
  isServiceMapTypeSourceFile,
5231
5286
  isNodeReferenceToServiceMapModuleApi,
5232
5287
  effectType,
5288
+ streamType,
5233
5289
  strictEffectType,
5234
5290
  layerType,
5235
5291
  fiberType,
@@ -5457,7 +5513,7 @@ var catchAllToMapError = createDiagnostic({
5457
5513
  const { failArg, failCall } = failCallInfo;
5458
5514
  report({
5459
5515
  location: transformation.callee,
5460
- 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\`.`,
5461
5517
  fixes: [{
5462
5518
  fixName: "catchAllToMapError_fix",
5463
5519
  description: "Replace with Effect.mapError",
@@ -5521,7 +5577,7 @@ var catchUnfailableEffect = createDiagnostic({
5521
5577
  if (E.flags & ts.TypeFlags.Never) {
5522
5578
  report({
5523
5579
  location: transformation.callee,
5524
- 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.",
5525
5581
  fixes: []
5526
5582
  });
5527
5583
  }
@@ -5584,7 +5640,7 @@ var classSelfMismatch = createDiagnostic({
5584
5640
  if (actualName !== expectedName) {
5585
5641
  report({
5586
5642
  location: selfTypeNode,
5587
- messageText: `Self type parameter should be '${expectedName}'`,
5643
+ messageText: `The \`Self\` type parameter for this class should be \`${expectedName}\`.`,
5588
5644
  fixes: [{
5589
5645
  fixName: "classSelfMismatch_fix",
5590
5646
  description: `Replace '${actualName}' with '${expectedName}'`,
@@ -5774,7 +5830,7 @@ var deterministicKeys = createDiagnostic({
5774
5830
  if (actualIdentifier !== expectedKey) {
5775
5831
  report({
5776
5832
  location: keyStringLiteral,
5777
- messageText: `Key should be '${expectedKey}'`,
5833
+ messageText: `This key does not match the deterministic key for this declaration. The expected key is \`${expectedKey}\`.`,
5778
5834
  fixes: [{
5779
5835
  fixName: "deterministicKeys_fix",
5780
5836
  description: `Replace '${actualIdentifier}' with '${expectedKey}'`,
@@ -5813,9 +5869,8 @@ var duplicatePackage = createDiagnostic({
5813
5869
  const versions = Object.keys(resolvedPackages[packageName]);
5814
5870
  report({
5815
5871
  location: sourceFile.statements[0],
5816
- messageText: `Package ${packageName} is referenced multiple times with different versions (${versions.join(", ")}) and may cause unexpected type errors.
5817
- Cleanup your dependencies and your package lockfile to avoid multiple instances of this package and reload the project.
5818
- 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]))}.
5819
5874
 
5820
5875
  ${versions.map((version) => `- found ${version} at ${resolvedPackages[packageName][version]}`).join("\n")}`,
5821
5876
  fixes: []
@@ -5923,7 +5978,7 @@ var effectFnIife = createDiagnostic({
5923
5978
  const traceExpressionText = traceExpression ? sourceFile.text.slice(traceExpression.pos, traceExpression.end) : void 0;
5924
5979
  report({
5925
5980
  location: node,
5926
- 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` : ``}.`,
5927
5982
  fixes
5928
5983
  });
5929
5984
  }
@@ -6008,7 +6063,7 @@ var effectFnImplicitAny = createDiagnostic({
6008
6063
  const parameterName = getParameterName(ts, parameter.name);
6009
6064
  report({
6010
6065
  location: parameter.name,
6011
- 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.`,
6012
6067
  fixes: []
6013
6068
  });
6014
6069
  }
@@ -6604,7 +6659,7 @@ var effectFnOpportunity = createDiagnostic({
6604
6659
  const expectedSignature = generateExpectedSignature();
6605
6660
  report({
6606
6661
  location: nameIdentifier ?? targetNode,
6607
- messageText: `Can be rewritten as a reusable function: ${expectedSignature}`,
6662
+ messageText: `This expression can be rewritten in the reusable function form \`${expectedSignature}\`.`,
6608
6663
  fixes
6609
6664
  });
6610
6665
  }
@@ -6816,7 +6871,7 @@ var effectMapVoid = createDiagnostic({
6816
6871
  if (isNone2(match2)) continue;
6817
6872
  report({
6818
6873
  location: node.expression,
6819
- 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.",
6820
6875
  fixes: [{
6821
6876
  fixName: "effectMapVoid_fix",
6822
6877
  description: "Replace with Effect.asVoid",
@@ -6871,7 +6926,7 @@ var effectSucceedWithVoid = createDiagnostic({
6871
6926
  if (!tsUtils.isVoidExpression(argument)) continue;
6872
6927
  report({
6873
6928
  location: node,
6874
- 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)`.",
6875
6930
  fixes: [{
6876
6931
  fixName: "effectSucceedWithVoid_fix",
6877
6932
  description: "Replace with Effect.void",
@@ -6933,7 +6988,7 @@ var extendsNativeError = createDiagnostic({
6933
6988
  if (isNativeError) {
6934
6989
  report({
6935
6990
  location: node.name ?? typeExpression,
6936
- 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.",
6937
6992
  fixes: []
6938
6993
  });
6939
6994
  }
@@ -6978,7 +7033,12 @@ var floatingEffect = createDiagnostic({
6978
7033
  if (!isFloatingExpression(node)) continue;
6979
7034
  const type = typeCheckerUtils.getTypeAtLocation(node.expression);
6980
7035
  if (!type) continue;
6981
- 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
+ );
6982
7042
  if (isSome2(effect)) {
6983
7043
  const allowedFloatingEffects = yield* pipe(
6984
7044
  typeParser.fiberType(type, node.expression),
@@ -6987,10 +7047,9 @@ var floatingEffect = createDiagnostic({
6987
7047
  );
6988
7048
  if (isNone2(allowedFloatingEffects)) {
6989
7049
  const isStrictEffect = yield* option(typeParser.strictEffectType(type, node.expression));
6990
- const name = isSome2(isStrictEffect) ? "Effect" : "Effect-able " + typeChecker.typeToString(type);
6991
7050
  report({
6992
7051
  location: node,
6993
- 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.`,
6994
7053
  fixes: []
6995
7054
  });
6996
7055
  }
@@ -7085,7 +7144,7 @@ var makeGlobalConsoleApply = (checkInEffect) => fn(`globalConsole${checkInEffect
7085
7144
  if (inEffect !== checkInEffect) continue;
7086
7145
  report({
7087
7146
  location: node,
7088
- 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}\`.`,
7089
7148
  fixes: []
7090
7149
  });
7091
7150
  }
@@ -7134,10 +7193,10 @@ var makeGlobalDateApply = (checkInEffect) => fn(`globalDate${checkInEffect ? "In
7134
7193
  let objectNode;
7135
7194
  if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.idText(node.expression.name) === "now") {
7136
7195
  objectNode = node.expression.expression;
7137
- 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.";
7138
7197
  } else if (ts.isNewExpression(node)) {
7139
7198
  objectNode = node.expression;
7140
- 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.";
7141
7200
  }
7142
7201
  if (!messageText || !objectNode) continue;
7143
7202
  const symbol3 = typeChecker.getSymbolAtLocation(objectNode);
@@ -7220,7 +7279,7 @@ var globalErrorInEffectCatch = createDiagnostic({
7220
7279
  );
7221
7280
  report({
7222
7281
  location: node.expression,
7223
- 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.`,
7224
7283
  fixes: []
7225
7284
  });
7226
7285
  }
@@ -7300,7 +7359,7 @@ var makeGlobalFetchApply = (checkInEffect) => fn(`globalFetch${checkInEffect ? "
7300
7359
  if (!fetchSymbol) return;
7301
7360
  const effectVersion = typeParser.supportedEffect();
7302
7361
  const packageName = effectVersion === "v3" ? "@effect/platform" : "effect/unstable/http";
7303
- 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}\`.`;
7304
7363
  const nodeToVisit = [];
7305
7364
  const appendNodeToVisit = (node) => {
7306
7365
  nodeToVisit.push(node);
@@ -7373,7 +7432,7 @@ var makeGlobalRandomApply = (checkInEffect) => fn(`globalRandom${checkInEffect ?
7373
7432
  if (inEffect !== checkInEffect) continue;
7374
7433
  report({
7375
7434
  location: node,
7376
- 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.",
7377
7436
  fixes: []
7378
7437
  });
7379
7438
  }
@@ -7404,12 +7463,12 @@ var globalRandom = createDiagnostic({
7404
7463
  // src/diagnostics/globalTimersInEffect.ts
7405
7464
  var timerAlternatives = {
7406
7465
  "setTimeout": {
7407
- inEffect: "Prefer using Effect.sleep or Schedule from Effect instead of setTimeout inside Effect generators.",
7408
- 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."
7409
7468
  },
7410
7469
  "setInterval": {
7411
- inEffect: "Prefer using Schedule or Effect.repeat from Effect instead of setInterval inside Effect generators.",
7412
- 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."
7413
7472
  }
7414
7473
  };
7415
7474
  var makeGlobalTimersApply = (checkInEffect) => fn(`globalTimers${checkInEffect ? "InEffect" : ""}.apply`)(function* (sourceFile, report) {
@@ -7651,7 +7710,7 @@ var instanceOfSchema = createDiagnostic({
7651
7710
  if (isSchemaType._tag === "Some") {
7652
7711
  report({
7653
7712
  location: node,
7654
- 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.",
7655
7714
  fixes: [{
7656
7715
  fixName: "instanceOfSchema_fix",
7657
7716
  description: "Replace with Schema.is",
@@ -7921,7 +7980,7 @@ var leakingRequirements = createDiagnostic({
7921
7980
  location: node,
7922
7981
  messageText: `Methods of this Service require \`${requirementsStr}\` from every caller.
7923
7982
 
7924
- 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.
7925
7984
 
7926
7985
  Resolve these dependencies at Layer creation and provide them to each method, so the service's type reflects its purpose, not its implementation.
7927
7986
 
@@ -8118,7 +8177,7 @@ var missedPipeableOpportunity = createDiagnostic({
8118
8177
  ).trim() : "";
8119
8178
  report({
8120
8179
  location: flow2.node,
8121
- 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.`,
8122
8181
  fixes: [{
8123
8182
  fixName: "missedPipeableOpportunity_fix",
8124
8183
  description: "Convert to pipe style",
@@ -8199,7 +8258,7 @@ var missingEffectContext = createDiagnostic({
8199
8258
  (missingTypes) => missingTypes.length > 0 ? report(
8200
8259
  {
8201
8260
  location: node,
8202
- 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(" | ")}\`.`,
8203
8262
  fixes: []
8204
8263
  }
8205
8264
  ) : void 0
@@ -8550,7 +8609,7 @@ var missingReturnYieldStar = createDiagnostic({
8550
8609
  }];
8551
8610
  report({
8552
8611
  location: unwrapped,
8553
- 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.",
8554
8613
  fixes: fix
8555
8614
  });
8556
8615
  }
@@ -8606,7 +8665,7 @@ var missingStarInYieldEffectGen = createDiagnostic({
8606
8665
  brokenGenerators.forEach(
8607
8666
  (pos) => report({
8608
8667
  location: { pos, end: pos + "function".length },
8609
- 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.",
8610
8669
  fixes: []
8611
8670
  })
8612
8671
  );
@@ -8628,7 +8687,7 @@ var missingStarInYieldEffectGen = createDiagnostic({
8628
8687
  }] : [];
8629
8688
  report({
8630
8689
  location: node,
8631
- 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.",
8632
8691
  fixes: fix
8633
8692
  });
8634
8693
  });
@@ -8696,7 +8755,7 @@ var multipleEffectProvide = createDiagnostic({
8696
8755
  if (chunk.length < 2) continue;
8697
8756
  report({
8698
8757
  location: chunk[0].node,
8699
- 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.",
8700
8759
  fixes: [{
8701
8760
  fixName: "multipleEffectProvide_fix",
8702
8761
  description: "Combine into a single provide",
@@ -8786,7 +8845,7 @@ var nodeBuiltinImport = createDiagnostic({
8786
8845
  if (match2) {
8787
8846
  report({
8788
8847
  location: statement.moduleSpecifier,
8789
- 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}\`.`,
8790
8849
  fixes: []
8791
8850
  });
8792
8851
  }
@@ -8799,7 +8858,7 @@ var nodeBuiltinImport = createDiagnostic({
8799
8858
  if (match2) {
8800
8859
  report({
8801
8860
  location: arg,
8802
- 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}\`.`,
8803
8862
  fixes: []
8804
8863
  });
8805
8864
  }
@@ -8853,7 +8912,7 @@ var nonObjectEffectServiceType = createDiagnostic({
8853
8912
  const propertyValue = property.initializer;
8854
8913
  const errorToReport = {
8855
8914
  location: property.name,
8856
- 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.",
8857
8916
  fixes: []
8858
8917
  };
8859
8918
  if (propertyName === "succeed") {
@@ -9615,7 +9674,7 @@ var outdatedApi = createDiagnostic({
9615
9674
  hasReported = true;
9616
9675
  report({
9617
9676
  location: propertyAccess.name,
9618
- 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.`,
9619
9678
  fixes: []
9620
9679
  });
9621
9680
  }
@@ -9658,7 +9717,7 @@ var outdatedApi = createDiagnostic({
9658
9717
  if (hasReported) {
9659
9718
  report({
9660
9719
  location: { pos: 0, end: 0 },
9661
- 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.",
9662
9721
  fixes: []
9663
9722
  });
9664
9723
  }
@@ -10903,7 +10962,7 @@ var overriddenSchemaConstructor = createDiagnostic({
10903
10962
  };
10904
10963
  report({
10905
10964
  location: member,
10906
- 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.",
10907
10966
  fixes: (member.body ? [fixAsStaticNew] : []).concat([{
10908
10967
  fixName: "overriddenSchemaConstructor_fix",
10909
10968
  description: "Remove the constructor override",
@@ -11025,7 +11084,7 @@ var preferSchemaOverJson = createDiagnostic({
11025
11084
  if (isSome2(match2)) {
11026
11085
  report({
11027
11086
  location: match2.value,
11028
- 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.",
11029
11088
  fixes: []
11030
11089
  });
11031
11090
  }
@@ -11143,9 +11202,7 @@ var returnEffectInGen = createDiagnostic({
11143
11202
  }] : [];
11144
11203
  report({
11145
11204
  location: node,
11146
- messageText: `You are returning an Effect-able type inside a generator function, and will result in nested Effect<Effect<...>>.
11147
- Maybe you wanted to return yield* instead?
11148
- 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.",
11149
11206
  fixes: fix
11150
11207
  });
11151
11208
  }),
@@ -11300,9 +11357,7 @@ var runEffectInsideEffect = createDiagnostic({
11300
11357
  );
11301
11358
  });
11302
11359
  const v4MethodName = `${isEffectRunCall.value.methodName}With`;
11303
- const messageText = supportedEffect === "v4" ? `Using ${nodeText} inside an Effect is not recommended. The same services should generally be used instead to run child effects.
11304
- 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.
11305
- 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}\`.`;
11306
11361
  report({
11307
11362
  location: node.expression,
11308
11363
  messageText,
@@ -11315,7 +11370,7 @@ Consider extracting the Runtime by using for example Effect.runtime and then use
11315
11370
  } else {
11316
11371
  report({
11317
11372
  location: node.expression,
11318
- 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.`,
11319
11374
  fixes: []
11320
11375
  });
11321
11376
  }
@@ -11370,7 +11425,7 @@ var schemaStructWithTag = createDiagnostic({
11370
11425
  const otherProperties = arg.properties.filter((prop) => prop !== tagProperty);
11371
11426
  report({
11372
11427
  location: node,
11373
- 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.",
11374
11429
  fixes: [{
11375
11430
  fixName: "schemaStructWithTag_fix",
11376
11431
  description: "Replace with Schema.TaggedStruct",
@@ -11463,7 +11518,7 @@ var schemaSyncInEffect = createDiagnostic({
11463
11518
  const effectMethodName = syncToEffectMethod[isSchemaSyncCall.value.methodName];
11464
11519
  report({
11465
11520
  location: node.expression,
11466
- 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.`,
11467
11522
  fixes: []
11468
11523
  });
11469
11524
  }
@@ -11523,7 +11578,7 @@ var schemaUnionOfLiterals = createDiagnostic({
11523
11578
  const schemaLiteralExpression = firstLiteralCall.expression;
11524
11579
  report({
11525
11580
  location: node,
11526
- 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.",
11527
11582
  fixes: [{
11528
11583
  fixName: "schemaUnionOfLiterals_fix",
11529
11584
  description: "Replace with a single Schema.Literal call",
@@ -11586,8 +11641,7 @@ var scopeInLayerEffect = createDiagnostic({
11586
11641
  map4(
11587
11642
  () => report({
11588
11643
  location: node,
11589
- messageText: `Seems like you are constructing a layer with a scope in the requirements.
11590
- 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.",
11591
11645
  fixes: methodIdentifier ? [{
11592
11646
  fixName: "scopeInLayerEffect_scoped",
11593
11647
  description: "Use scoped for Layer creation",
@@ -11687,7 +11741,7 @@ var serviceNotAsClass = createDiagnostic({
11687
11741
  const shapeText = typeArgs.length > 0 ? typeArgs.map((t) => sourceFile.text.substring(ts.getTokenPosOfNode(t, sourceFile), t.end)).join(", ") : "Shape";
11688
11742
  report({
11689
11743
  location: callExpr,
11690
- 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, "")}") {}\`.`,
11691
11745
  fixes: [{
11692
11746
  fixName: "serviceNotAsClass",
11693
11747
  description: `Convert to class declaration`,
@@ -11900,7 +11954,7 @@ var tryCatchInEffectGen = createDiagnostic({
11900
11954
  map4(() => {
11901
11955
  report({
11902
11956
  location: node,
11903
- 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(", ")}).`,
11904
11958
  fixes: []
11905
11959
  });
11906
11960
  }),
@@ -11961,8 +12015,7 @@ var unknownInEffectCatch = createDiagnostic({
11961
12015
  );
11962
12016
  report({
11963
12017
  location: node.expression,
11964
- messageText: `The 'catch' callback in ${nodeText} returns 'unknown'. The catch callback should be used to provide typed errors.
11965
- 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\`.`,
11966
12019
  fixes: []
11967
12020
  });
11968
12021
  }
@@ -12059,7 +12112,7 @@ var unnecessaryFailYieldableError = createDiagnostic({
12059
12112
  map4(
12060
12113
  () => report({
12061
12114
  location: node,
12062
- 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`.",
12063
12116
  fixes: [{
12064
12117
  fixName: "unnecessaryFailYieldableError_fix",
12065
12118
  description: "Replace yield* Effect.fail with yield*",
@@ -12164,7 +12217,7 @@ var unnecessaryPipeChain = createDiagnostic({
12164
12217
  map4(({ innerCall, pipeCall }) => {
12165
12218
  report({
12166
12219
  location: node,
12167
- 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.",
12168
12221
  fixes: [{
12169
12222
  fixName: "unnecessaryPipeChain_fix",
12170
12223
  description: "Rewrite as single pipe call",