@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.
package/index.js CHANGED
@@ -4130,6 +4130,14 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
4130
4130
  ),
4131
4131
  ([A, E, R]) => ({ A, E, R })
4132
4132
  );
4133
+ const streamVarianceStruct = (type, atLocation) => map5(
4134
+ all(
4135
+ varianceStructCovariantType(type, atLocation, "_A"),
4136
+ varianceStructCovariantType(type, atLocation, "_E"),
4137
+ varianceStructCovariantType(type, atLocation, "_R")
4138
+ ),
4139
+ ([A, E, R]) => ({ A, E, R })
4140
+ );
4133
4141
  const layerVarianceStruct = (type, atLocation) => map5(
4134
4142
  all(
4135
4143
  varianceStructContravariantType(type, atLocation, "_ROut"),
@@ -4176,6 +4184,21 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
4176
4184
  "TypeParser.strictEffectType",
4177
4185
  (type) => type
4178
4186
  );
4187
+ const streamType = cachedBy(
4188
+ fn("TypeParser.streamType")(function* (type, atLocation) {
4189
+ if (supportedEffect() === "v3") {
4190
+ return yield* effectType(type, atLocation);
4191
+ }
4192
+ const typeIdSymbol = typeChecker.getPropertyOfType(type, "~effect/Stream");
4193
+ if (!typeIdSymbol) {
4194
+ return yield* typeParserIssue("Type is not a stream", type, atLocation);
4195
+ }
4196
+ const typeIdType = typeChecker.getTypeOfSymbolAtLocation(typeIdSymbol, atLocation);
4197
+ return yield* streamVarianceStruct(typeIdType, atLocation);
4198
+ }),
4199
+ "TypeParser.streamType",
4200
+ (type) => type
4201
+ );
4179
4202
  const isEffectTypeSourceFile = cachedBy(
4180
4203
  fn("TypeParser.isEffectTypeSourceFile")(function* (sourceFile) {
4181
4204
  const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
@@ -5911,6 +5934,7 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
5911
5934
  isServiceMapTypeSourceFile,
5912
5935
  isNodeReferenceToServiceMapModuleApi,
5913
5936
  effectType,
5937
+ streamType,
5914
5938
  strictEffectType,
5915
5939
  layerType,
5916
5940
  fiberType,
@@ -7369,7 +7393,7 @@ var catchAllToMapError = createDiagnostic({
7369
7393
  const { failArg, failCall } = failCallInfo;
7370
7394
  report({
7371
7395
  location: transformation.callee,
7372
- messageText: `You can use Effect.mapError instead of Effect.${catchAllName} + Effect.fail to transform the error type.`,
7396
+ messageText: `\`Effect.mapError\` expresses the same error-type transformation more directly than \`Effect.${catchAllName}\` followed by \`Effect.fail\`.`,
7373
7397
  fixes: [{
7374
7398
  fixName: "catchAllToMapError_fix",
7375
7399
  description: "Replace with Effect.mapError",
@@ -7433,7 +7457,7 @@ var catchUnfailableEffect = createDiagnostic({
7433
7457
  if (E.flags & ts.TypeFlags.Never) {
7434
7458
  report({
7435
7459
  location: transformation.callee,
7436
- messageText: `Looks like the previous effect never fails, so probably this error handling will never be triggered.`,
7460
+ messageText: "The previous Effect does not fail, so this error-handling branch will never run.",
7437
7461
  fixes: []
7438
7462
  });
7439
7463
  }
@@ -7496,7 +7520,7 @@ var classSelfMismatch = createDiagnostic({
7496
7520
  if (actualName !== expectedName) {
7497
7521
  report({
7498
7522
  location: selfTypeNode,
7499
- messageText: `Self type parameter should be '${expectedName}'`,
7523
+ messageText: `The \`Self\` type parameter for this class should be \`${expectedName}\`.`,
7500
7524
  fixes: [{
7501
7525
  fixName: "classSelfMismatch_fix",
7502
7526
  description: `Replace '${actualName}' with '${expectedName}'`,
@@ -7620,7 +7644,7 @@ var deterministicKeys = createDiagnostic({
7620
7644
  if (actualIdentifier !== expectedKey) {
7621
7645
  report({
7622
7646
  location: keyStringLiteral,
7623
- messageText: `Key should be '${expectedKey}'`,
7647
+ messageText: `This key does not match the deterministic key for this declaration. The expected key is \`${expectedKey}\`.`,
7624
7648
  fixes: [{
7625
7649
  fixName: "deterministicKeys_fix",
7626
7650
  description: `Replace '${actualIdentifier}' with '${expectedKey}'`,
@@ -7659,9 +7683,8 @@ var duplicatePackage = createDiagnostic({
7659
7683
  const versions = Object.keys(resolvedPackages[packageName]);
7660
7684
  report({
7661
7685
  location: sourceFile.statements[0],
7662
- messageText: `Package ${packageName} is referenced multiple times with different versions (${versions.join(", ")}) and may cause unexpected type errors.
7663
- Cleanup your dependencies and your package lockfile to avoid multiple instances of this package and reload the project.
7664
- If this is intended set the LSP config "allowedDuplicatedPackages" to ${JSON.stringify(options.allowedDuplicatedPackages.concat([packageName]))}.
7686
+ messageText: `Multiple versions of package \`${packageName}\` were detected: ${versions.join(", ")}. Package duplication can change runtime identity and type equality across Effect modules.
7687
+ If this is intentional, set the LSP config \`allowedDuplicatedPackages\` to ${JSON.stringify(options.allowedDuplicatedPackages.concat([packageName]))}.
7665
7688
 
7666
7689
  ${versions.map((version) => `- found ${version} at ${resolvedPackages[packageName][version]}`).join("\n")}`,
7667
7690
  fixes: []
@@ -7769,7 +7792,7 @@ var effectFnIife = createDiagnostic({
7769
7792
  const traceExpressionText = traceExpression ? sourceFile.text.slice(traceExpression.pos, traceExpression.end) : void 0;
7770
7793
  report({
7771
7794
  location: node,
7772
- 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` : ``}.`,
7795
+ 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` : ``}.`,
7773
7796
  fixes
7774
7797
  });
7775
7798
  }
@@ -7854,7 +7877,7 @@ var effectFnImplicitAny = createDiagnostic({
7854
7877
  const parameterName = getParameterName(ts, parameter.name);
7855
7878
  report({
7856
7879
  location: parameter.name,
7857
- messageText: `Parameter '${parameterName}' implicitly has an 'any' type in Effect.fn/Effect.fnUntraced. Add an explicit type annotation or provide a contextual function type.`,
7880
+ 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.`,
7858
7881
  fixes: []
7859
7882
  });
7860
7883
  }
@@ -8450,7 +8473,7 @@ var effectFnOpportunity = createDiagnostic({
8450
8473
  const expectedSignature = generateExpectedSignature();
8451
8474
  report({
8452
8475
  location: nameIdentifier ?? targetNode,
8453
- messageText: `Can be rewritten as a reusable function: ${expectedSignature}`,
8476
+ messageText: `This expression can be rewritten in the reusable function form \`${expectedSignature}\`.`,
8454
8477
  fixes
8455
8478
  });
8456
8479
  }
@@ -8662,7 +8685,7 @@ var effectMapVoid = createDiagnostic({
8662
8685
  if (isNone2(match2)) continue;
8663
8686
  report({
8664
8687
  location: node.expression,
8665
- messageText: "Effect.asVoid can be used instead to discard the success value",
8688
+ messageText: "This expression discards the success value through mapping. `Effect.asVoid` represents that form directly.",
8666
8689
  fixes: [{
8667
8690
  fixName: "effectMapVoid_fix",
8668
8691
  description: "Replace with Effect.asVoid",
@@ -8717,7 +8740,7 @@ var effectSucceedWithVoid = createDiagnostic({
8717
8740
  if (!tsUtils.isVoidExpression(argument)) continue;
8718
8741
  report({
8719
8742
  location: node,
8720
- messageText: "Effect.void can be used instead of Effect.succeed(undefined) or Effect.succeed(void 0)",
8743
+ messageText: "`Effect.void` represents the same outcome as `Effect.succeed(undefined)` or `Effect.succeed(void 0)`.",
8721
8744
  fixes: [{
8722
8745
  fixName: "effectSucceedWithVoid_fix",
8723
8746
  description: "Replace with Effect.void",
@@ -8779,7 +8802,7 @@ var extendsNativeError = createDiagnostic({
8779
8802
  if (isNativeError) {
8780
8803
  report({
8781
8804
  location: node.name ?? typeExpression,
8782
- 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.",
8805
+ messageText: "This class extends the native `Error` type directly. Untagged native errors lose distinction in the Effect failure channel.",
8783
8806
  fixes: []
8784
8807
  });
8785
8808
  }
@@ -8824,7 +8847,12 @@ var floatingEffect = createDiagnostic({
8824
8847
  if (!isFloatingExpression(node)) continue;
8825
8848
  const type = typeCheckerUtils.getTypeAtLocation(node.expression);
8826
8849
  if (!type) continue;
8827
- const effect = yield* option(typeParser.effectType(type, node.expression));
8850
+ const effect = yield* option(
8851
+ pipe(
8852
+ typeParser.effectType(type, node.expression),
8853
+ orElse2(() => typeParser.streamType(type, node.expression))
8854
+ )
8855
+ );
8828
8856
  if (isSome2(effect)) {
8829
8857
  const allowedFloatingEffects = yield* pipe(
8830
8858
  typeParser.fiberType(type, node.expression),
@@ -8833,10 +8861,9 @@ var floatingEffect = createDiagnostic({
8833
8861
  );
8834
8862
  if (isNone2(allowedFloatingEffects)) {
8835
8863
  const isStrictEffect = yield* option(typeParser.strictEffectType(type, node.expression));
8836
- const name = isSome2(isStrictEffect) ? "Effect" : "Effect-able " + typeChecker.typeToString(type);
8837
8864
  report({
8838
8865
  location: node,
8839
- messageText: `${name} must be yielded or assigned to a variable.`,
8866
+ 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.`,
8840
8867
  fixes: []
8841
8868
  });
8842
8869
  }
@@ -8931,7 +8958,7 @@ var makeGlobalConsoleApply = (checkInEffect) => fn(`globalConsole${checkInEffect
8931
8958
  if (inEffect !== checkInEffect) continue;
8932
8959
  report({
8933
8960
  location: node,
8934
- messageText: checkInEffect ? `Prefer using ${alternative} instead of console.${method} inside Effect generators.` : `Prefer using ${alternative} instead of console.${method}.`,
8961
+ 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}\`.`,
8935
8962
  fixes: []
8936
8963
  });
8937
8964
  }
@@ -8980,10 +9007,10 @@ var makeGlobalDateApply = (checkInEffect) => fn(`globalDate${checkInEffect ? "In
8980
9007
  let objectNode;
8981
9008
  if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.idText(node.expression.name) === "now") {
8982
9009
  objectNode = node.expression.expression;
8983
- 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().";
9010
+ 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.";
8984
9011
  } else if (ts.isNewExpression(node)) {
8985
9012
  objectNode = node.expression;
8986
- messageText = checkInEffect ? "Prefer using DateTime from Effect instead of new Date() inside Effect generators." : "Prefer using DateTime from Effect instead of new Date().";
9013
+ 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.";
8987
9014
  }
8988
9015
  if (!messageText || !objectNode) continue;
8989
9016
  const symbol3 = typeChecker.getSymbolAtLocation(objectNode);
@@ -9066,7 +9093,7 @@ var globalErrorInEffectCatch = createDiagnostic({
9066
9093
  );
9067
9094
  report({
9068
9095
  location: node.expression,
9069
- 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.`,
9096
+ 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.`,
9070
9097
  fixes: []
9071
9098
  });
9072
9099
  }
@@ -9146,7 +9173,7 @@ var makeGlobalFetchApply = (checkInEffect) => fn(`globalFetch${checkInEffect ? "
9146
9173
  if (!fetchSymbol) return;
9147
9174
  const effectVersion = typeParser.supportedEffect();
9148
9175
  const packageName = effectVersion === "v3" ? "@effect/platform" : "effect/unstable/http";
9149
- 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.`;
9176
+ 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}\`.`;
9150
9177
  const nodeToVisit = [];
9151
9178
  const appendNodeToVisit = (node) => {
9152
9179
  nodeToVisit.push(node);
@@ -9219,7 +9246,7 @@ var makeGlobalRandomApply = (checkInEffect) => fn(`globalRandom${checkInEffect ?
9219
9246
  if (inEffect !== checkInEffect) continue;
9220
9247
  report({
9221
9248
  location: node,
9222
- 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().",
9249
+ 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.",
9223
9250
  fixes: []
9224
9251
  });
9225
9252
  }
@@ -9250,12 +9277,12 @@ var globalRandom = createDiagnostic({
9250
9277
  // src/diagnostics/globalTimersInEffect.ts
9251
9278
  var timerAlternatives = {
9252
9279
  "setTimeout": {
9253
- inEffect: "Prefer using Effect.sleep or Schedule from Effect instead of setTimeout inside Effect generators.",
9254
- outsideEffect: "Prefer using Effect.sleep or Schedule from Effect instead of setTimeout."
9280
+ inEffect: "This Effect code uses `setTimeout`, the corresponding timer API in this context is `Effect.sleep or Schedule` from Effect.",
9281
+ outsideEffect: "This code uses `setTimeout`, the corresponding Effect timer API is `Effect.sleep or Schedule` from Effect."
9255
9282
  },
9256
9283
  "setInterval": {
9257
- inEffect: "Prefer using Schedule or Effect.repeat from Effect instead of setInterval inside Effect generators.",
9258
- outsideEffect: "Prefer using Schedule or Effect.repeat from Effect instead of setInterval."
9284
+ inEffect: "This Effect code uses `setInterval`, the corresponding timer API in this context is `Schedule or Effect.repeat` from Effect.",
9285
+ outsideEffect: "This code uses `setInterval`, the corresponding Effect timer API is `Schedule or Effect.repeat` from Effect."
9259
9286
  }
9260
9287
  };
9261
9288
  var makeGlobalTimersApply = (checkInEffect) => fn(`globalTimers${checkInEffect ? "InEffect" : ""}.apply`)(function* (sourceFile, report) {
@@ -9497,7 +9524,7 @@ var instanceOfSchema = createDiagnostic({
9497
9524
  if (isSchemaType._tag === "Some") {
9498
9525
  report({
9499
9526
  location: node,
9500
- messageText: "Consider using Schema.is instead of instanceof for Effect Schema types.",
9527
+ messageText: "This code uses `instanceof` with an Effect Schema type. `Schema.is` is the schema-aware runtime check for this case.",
9501
9528
  fixes: [{
9502
9529
  fixName: "instanceOfSchema_fix",
9503
9530
  description: "Replace with Schema.is",
@@ -9767,7 +9794,7 @@ var leakingRequirements = createDiagnostic({
9767
9794
  location: node,
9768
9795
  messageText: `Methods of this Service require \`${requirementsStr}\` from every caller.
9769
9796
 
9770
- 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.
9797
+ The requirement becomes part of the public service surface instead of remaining internal to Layer implementation.
9771
9798
 
9772
9799
  Resolve these dependencies at Layer creation and provide them to each method, so the service's type reflects its purpose, not its implementation.
9773
9800
 
@@ -9964,7 +9991,7 @@ var missedPipeableOpportunity = createDiagnostic({
9964
9991
  ).trim() : "";
9965
9992
  report({
9966
9993
  location: flow2.node,
9967
- messageText: `Nested function calls can be converted to pipeable style for better readability; consider using ${subjectText}.pipe(...) instead.`,
9994
+ 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.`,
9968
9995
  fixes: [{
9969
9996
  fixName: "missedPipeableOpportunity_fix",
9970
9997
  description: "Convert to pipe style",
@@ -10045,7 +10072,7 @@ var missingEffectContext = createDiagnostic({
10045
10072
  (missingTypes) => missingTypes.length > 0 ? report(
10046
10073
  {
10047
10074
  location: node,
10048
- messageText: `Missing '${sortTypes(missingTypes).map((_) => typeChecker.typeToString(_)).join(" | ")}' in the expected Effect context.`,
10075
+ messageText: `This Effect requires a service that is missing from the expected Effect context: \`${sortTypes(missingTypes).map((_) => typeChecker.typeToString(_)).join(" | ")}\`.`,
10049
10076
  fixes: []
10050
10077
  }
10051
10078
  ) : void 0
@@ -10396,7 +10423,7 @@ var missingReturnYieldStar = createDiagnostic({
10396
10423
  }];
10397
10424
  report({
10398
10425
  location: unwrapped,
10399
- 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.`,
10426
+ messageText: "This Effect never succeeds; using `return yield*` preserves a definitive generator exit point for type narrowing and tooling support.",
10400
10427
  fixes: fix
10401
10428
  });
10402
10429
  }
@@ -10452,7 +10479,7 @@ var missingStarInYieldEffectGen = createDiagnostic({
10452
10479
  brokenGenerators.forEach(
10453
10480
  (pos) => report({
10454
10481
  location: { pos, end: pos + "function".length },
10455
- messageText: `Seems like you used yield instead of yield* inside this Effect.gen.`,
10482
+ messageText: "This uses `yield` for an `Effect` value. `yield*` is the Effect-aware form in this context.",
10456
10483
  fixes: []
10457
10484
  })
10458
10485
  );
@@ -10474,7 +10501,7 @@ var missingStarInYieldEffectGen = createDiagnostic({
10474
10501
  }] : [];
10475
10502
  report({
10476
10503
  location: node,
10477
- messageText: `When yielding Effects inside Effect.gen, you should use yield* instead of yield.`,
10504
+ messageText: "This uses `yield` for an `Effect` value. `yield*` is the Effect-aware form in this context.",
10478
10505
  fixes: fix
10479
10506
  });
10480
10507
  });
@@ -10542,7 +10569,7 @@ var multipleEffectProvide = createDiagnostic({
10542
10569
  if (chunk.length < 2) continue;
10543
10570
  report({
10544
10571
  location: chunk[0].node,
10545
- messageText: "Avoid chaining Effect.provide calls, as this can lead to service lifecycle issues. Instead, merge layers and provide them in a single call.",
10572
+ 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.",
10546
10573
  fixes: [{
10547
10574
  fixName: "multipleEffectProvide_fix",
10548
10575
  description: "Combine into a single provide",
@@ -10632,7 +10659,7 @@ var nodeBuiltinImport = createDiagnostic({
10632
10659
  if (match2) {
10633
10660
  report({
10634
10661
  location: statement.moduleSpecifier,
10635
- messageText: `Prefer using ${match2.alternative} from ${match2.package} instead of the Node.js '${match2.module}' module.`,
10662
+ messageText: `This module reference uses the \`${match2.module}\` module, the corresponding Effect API is \`${match2.alternative}\` from \`${match2.package}\`.`,
10636
10663
  fixes: []
10637
10664
  });
10638
10665
  }
@@ -10645,7 +10672,7 @@ var nodeBuiltinImport = createDiagnostic({
10645
10672
  if (match2) {
10646
10673
  report({
10647
10674
  location: arg,
10648
- messageText: `Prefer using ${match2.alternative} from ${match2.package} instead of the Node.js '${match2.module}' module.`,
10675
+ messageText: `This module reference uses the \`${match2.module}\` module, the corresponding Effect API is \`${match2.alternative}\` from \`${match2.package}\`.`,
10649
10676
  fixes: []
10650
10677
  });
10651
10678
  }
@@ -10699,7 +10726,7 @@ var nonObjectEffectServiceType = createDiagnostic({
10699
10726
  const propertyValue = property.initializer;
10700
10727
  const errorToReport = {
10701
10728
  location: property.name,
10702
- 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.",
10729
+ 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.",
10703
10730
  fixes: []
10704
10731
  };
10705
10732
  if (propertyName === "succeed") {
@@ -11461,7 +11488,7 @@ var outdatedApi = createDiagnostic({
11461
11488
  hasReported = true;
11462
11489
  report({
11463
11490
  location: propertyAccess.name,
11464
- messageText: `${propertyName} is an Effect v3 API, but the project is using Effect v4.`,
11491
+ 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.`,
11465
11492
  fixes: []
11466
11493
  });
11467
11494
  }
@@ -11504,7 +11531,7 @@ var outdatedApi = createDiagnostic({
11504
11531
  if (hasReported) {
11505
11532
  report({
11506
11533
  location: { pos: 0, end: 0 },
11507
- 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.",
11534
+ 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.",
11508
11535
  fixes: []
11509
11536
  });
11510
11537
  }
@@ -11680,7 +11707,7 @@ var overriddenSchemaConstructor = createDiagnostic({
11680
11707
  };
11681
11708
  report({
11682
11709
  location: member,
11683
- 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.",
11710
+ 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.",
11684
11711
  fixes: (member.body ? [fixAsStaticNew] : []).concat([{
11685
11712
  fixName: "overriddenSchemaConstructor_fix",
11686
11713
  description: "Remove the constructor override",
@@ -11802,7 +11829,7 @@ var preferSchemaOverJson = createDiagnostic({
11802
11829
  if (isSome2(match2)) {
11803
11830
  report({
11804
11831
  location: match2.value,
11805
- messageText: "Consider using Effect Schema for JSON operations instead of JSON.parse/JSON.stringify",
11832
+ messageText: "This code uses `JSON.parse` or `JSON.stringify`. Effect Schema provides Effect-aware APIs for JSON parsing and stringifying.",
11806
11833
  fixes: []
11807
11834
  });
11808
11835
  }
@@ -11920,9 +11947,7 @@ var returnEffectInGen = createDiagnostic({
11920
11947
  }] : [];
11921
11948
  report({
11922
11949
  location: node,
11923
- messageText: `You are returning an Effect-able type inside a generator function, and will result in nested Effect<Effect<...>>.
11924
- Maybe you wanted to return yield* instead?
11925
- 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.`,
11950
+ 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.",
11926
11951
  fixes: fix
11927
11952
  });
11928
11953
  }),
@@ -12077,9 +12102,7 @@ var runEffectInsideEffect = createDiagnostic({
12077
12102
  );
12078
12103
  });
12079
12104
  const v4MethodName = `${isEffectRunCall.value.methodName}With`;
12080
- const messageText = supportedEffect === "v4" ? `Using ${nodeText} inside an Effect is not recommended. The same services should generally be used instead to run child effects.
12081
- 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.
12082
- Consider extracting the Runtime by using for example Effect.runtime and then use Runtime.${isEffectRunCall.value.methodName} with the extracted runtime instead.`;
12105
+ 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}\`.`;
12083
12106
  report({
12084
12107
  location: node.expression,
12085
12108
  messageText,
@@ -12092,7 +12115,7 @@ Consider extracting the Runtime by using for example Effect.runtime and then use
12092
12115
  } else {
12093
12116
  report({
12094
12117
  location: node.expression,
12095
- messageText: `Using ${nodeText} inside an Effect is not recommended. Effects inside generators can usually just be yielded.`,
12118
+ messageText: `\`${nodeText}\` is called inside an existing Effect context. Here, the inner Effect can be used directly.`,
12096
12119
  fixes: []
12097
12120
  });
12098
12121
  }
@@ -12147,7 +12170,7 @@ var schemaStructWithTag = createDiagnostic({
12147
12170
  const otherProperties = arg.properties.filter((prop) => prop !== tagProperty);
12148
12171
  report({
12149
12172
  location: node,
12150
- messageText: "Schema.Struct with a _tag field can be simplified to Schema.TaggedStruct to make the tag optional in the constructor.",
12173
+ 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.",
12151
12174
  fixes: [{
12152
12175
  fixName: "schemaStructWithTag_fix",
12153
12176
  description: "Replace with Schema.TaggedStruct",
@@ -12240,7 +12263,7 @@ var schemaSyncInEffect = createDiagnostic({
12240
12263
  const effectMethodName = syncToEffectMethod[isSchemaSyncCall.value.methodName];
12241
12264
  report({
12242
12265
  location: node.expression,
12243
- messageText: `Using ${nodeText} inside an Effect generator is not recommended. Use Schema.${effectMethodName} instead to get properly typed error channel.`,
12266
+ messageText: `\`${nodeText}\` is used inside an Effect generator. \`Schema.${effectMethodName}\` preserves the typed Effect error channel for this operation without throwing.`,
12244
12267
  fixes: []
12245
12268
  });
12246
12269
  }
@@ -12300,7 +12323,7 @@ var schemaUnionOfLiterals = createDiagnostic({
12300
12323
  const schemaLiteralExpression = firstLiteralCall.expression;
12301
12324
  report({
12302
12325
  location: node,
12303
- messageText: "A Schema.Union of multiple Schema.Literal calls can be simplified to a single Schema.Literal call.",
12326
+ messageText: "This `Schema.Union` contains multiple `Schema.Literal` members and can be simplified to a single `Schema.Literal` call.",
12304
12327
  fixes: [{
12305
12328
  fixName: "schemaUnionOfLiterals_fix",
12306
12329
  description: "Replace with a single Schema.Literal call",
@@ -12363,8 +12386,7 @@ var scopeInLayerEffect = createDiagnostic({
12363
12386
  map5(
12364
12387
  () => report({
12365
12388
  location: node,
12366
- messageText: `Seems like you are constructing a layer with a scope in the requirements.
12367
- Consider using "scoped" instead to get rid of the scope in the requirements.`,
12389
+ messageText: "This layer construction leaves `Scope` in the requirement set. The scoped API removes `Scope` from the resulting requirements.",
12368
12390
  fixes: methodIdentifier ? [{
12369
12391
  fixName: "scopeInLayerEffect_scoped",
12370
12392
  description: "Use scoped for Layer creation",
@@ -12464,7 +12486,7 @@ var serviceNotAsClass = createDiagnostic({
12464
12486
  const shapeText = typeArgs.length > 0 ? typeArgs.map((t) => sourceFile.text.substring(ts.getTokenPosOfNode(t, sourceFile), t.end)).join(", ") : "Shape";
12465
12487
  report({
12466
12488
  location: callExpr,
12467
- 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, "")}") {}`,
12489
+ 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, "")}") {}\`.`,
12468
12490
  fixes: [{
12469
12491
  fixName: "serviceNotAsClass",
12470
12492
  description: `Convert to class declaration`,
@@ -12677,7 +12699,7 @@ var tryCatchInEffectGen = createDiagnostic({
12677
12699
  map5(() => {
12678
12700
  report({
12679
12701
  location: node,
12680
- messageText: `Avoid using try/catch inside Effect generators. Use Effect's error handling mechanisms instead (e.g. ${alternatives.join(", ")}).`,
12702
+ messageText: `This Effect generator contains \`try/catch\`; in this context, error handling is expressed with Effect APIs such as ${alternatives.join(", ")}).`,
12681
12703
  fixes: []
12682
12704
  });
12683
12705
  }),
@@ -12738,8 +12760,7 @@ var unknownInEffectCatch = createDiagnostic({
12738
12760
  );
12739
12761
  report({
12740
12762
  location: node.expression,
12741
- messageText: `The 'catch' callback in ${nodeText} returns 'unknown'. The catch callback should be used to provide typed errors.
12742
- Consider wrapping unknown errors into Effect's Data.TaggedError for example, or narrow down the type to the specific error raised.`,
12763
+ 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\`.`,
12743
12764
  fixes: []
12744
12765
  });
12745
12766
  }
@@ -12836,7 +12857,7 @@ var unnecessaryFailYieldableError = createDiagnostic({
12836
12857
  map5(
12837
12858
  () => report({
12838
12859
  location: node,
12839
- messageText: `This Effect.fail call uses a yieldable error type as argument. You can yield* the error directly instead.`,
12860
+ messageText: "This `yield* Effect.fail(...)` passes a yieldable error value. `yield*` represents that value directly without wrapping it in `Effect.fail`.",
12840
12861
  fixes: [{
12841
12862
  fixName: "unnecessaryFailYieldableError_fix",
12842
12863
  description: "Replace yield* Effect.fail with yield*",
@@ -12941,7 +12962,7 @@ var unnecessaryPipeChain = createDiagnostic({
12941
12962
  map5(({ innerCall, pipeCall }) => {
12942
12963
  report({
12943
12964
  location: node,
12944
- messageText: `Chained pipe calls can be simplified to a single pipe call`,
12965
+ messageText: "This expression contains chained `pipe` calls that can be simplified to a single `pipe` call.",
12945
12966
  fixes: [{
12946
12967
  fixName: "unnecessaryPipeChain_fix",
12947
12968
  description: "Rewrite as single pipe call",