@effect/language-service 0.84.2 → 0.85.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -27,7 +27,7 @@ __export(effect_lsp_patch_utils_exports, {
27
27
  });
28
28
  module.exports = __toCommonJS(effect_lsp_patch_utils_exports);
29
29
 
30
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Pipeable.js
30
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Pipeable.js
31
31
  var pipeArguments = (self, args3) => {
32
32
  switch (args3.length) {
33
33
  case 0:
@@ -60,7 +60,7 @@ var pipeArguments = (self, args3) => {
60
60
  }
61
61
  };
62
62
 
63
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Function.js
63
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Function.js
64
64
  var dual = function(arity, body) {
65
65
  if (typeof arity === "function") {
66
66
  return function() {
@@ -108,7 +108,7 @@ function pipe(a, ...args3) {
108
108
  return pipeArguments(a, args3);
109
109
  }
110
110
 
111
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/internal/equal.js
111
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/internal/equal.js
112
112
  var getAllObjectKeys = (obj) => {
113
113
  const keys2 = new Set(Reflect.ownKeys(obj));
114
114
  if (obj.constructor === Object) return keys2;
@@ -131,7 +131,7 @@ var getAllObjectKeys = (obj) => {
131
131
  };
132
132
  var byReferenceInstances = /* @__PURE__ */ new WeakSet();
133
133
 
134
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Predicate.js
134
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Predicate.js
135
135
  function isString(input) {
136
136
  return typeof input === "string";
137
137
  }
@@ -152,7 +152,7 @@ function isObjectKeyword(input) {
152
152
  }
153
153
  var hasProperty = /* @__PURE__ */ dual(2, (self, property) => isObjectKeyword(self) && property in self);
154
154
 
155
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Hash.js
155
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Hash.js
156
156
  var symbol = "~effect/interfaces/Hash";
157
157
  var hash = (self) => {
158
158
  switch (typeof self) {
@@ -271,7 +271,7 @@ function withVisitedTracking(obj, fn2) {
271
271
  return result;
272
272
  }
273
273
 
274
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Equal.js
274
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Equal.js
275
275
  var symbol2 = "~effect/interfaces/Equal";
276
276
  function equals() {
277
277
  if (arguments.length === 1) {
@@ -433,10 +433,10 @@ var compareSets = /* @__PURE__ */ makeCompareSet(compareBoth);
433
433
  var isEqual = (u) => hasProperty(u, symbol2);
434
434
  var asEquivalence = () => equals;
435
435
 
436
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/internal/array.js
436
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/internal/array.js
437
437
  var isArrayNonEmpty = (self) => self.length > 0;
438
438
 
439
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Redactable.js
439
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Redactable.js
440
440
  var symbolRedactable = /* @__PURE__ */ Symbol.for("~effect/Inspectable/redactable");
441
441
  var isRedactable = (u) => hasProperty(u, symbolRedactable);
442
442
  function redact(u) {
@@ -455,7 +455,7 @@ var emptyServiceMap = {
455
455
  }
456
456
  };
457
457
 
458
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Formatter.js
458
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Formatter.js
459
459
  function format(input, options) {
460
460
  const space = options?.space ?? 0;
461
461
  const seen = /* @__PURE__ */ new WeakSet();
@@ -534,7 +534,7 @@ function safeToString(input) {
534
534
  }
535
535
  }
536
536
 
537
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Inspectable.js
537
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Inspectable.js
538
538
  var NodeInspectSymbol = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
539
539
  var toJson = (input) => {
540
540
  try {
@@ -578,7 +578,7 @@ var Class = class {
578
578
  }
579
579
  };
580
580
 
581
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Utils.js
581
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Utils.js
582
582
  var SingleShotGen = class _SingleShotGen {
583
583
  called = false;
584
584
  self;
@@ -621,7 +621,7 @@ var forced = {
621
621
  var isNotOptimizedAway = /* @__PURE__ */ standard[InternalTypeId](() => new Error().stack)?.includes(InternalTypeId) === true;
622
622
  var internalCall = isNotOptimizedAway ? standard[InternalTypeId] : forced[InternalTypeId];
623
623
 
624
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/internal/core.js
624
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/internal/core.js
625
625
  var EffectTypeId = `~effect/Effect`;
626
626
  var ExitTypeId = `~effect/Exit`;
627
627
  var effectVariance = {
@@ -968,7 +968,7 @@ var DoneVoid = {
968
968
  value: void 0
969
969
  };
970
970
 
971
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/internal/option.js
971
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/internal/option.js
972
972
  var TypeId = "~effect/data/Option";
973
973
  var CommonProto = {
974
974
  [TypeId]: {
@@ -1039,7 +1039,7 @@ var some = (value) => {
1039
1039
  return a;
1040
1040
  };
1041
1041
 
1042
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/internal/result.js
1042
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/internal/result.js
1043
1043
  var TypeId2 = "~effect/data/Result";
1044
1044
  var CommonProto2 = {
1045
1045
  [TypeId2]: {
@@ -1110,13 +1110,13 @@ var succeed = (success) => {
1110
1110
  return a;
1111
1111
  };
1112
1112
 
1113
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Order.js
1113
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Order.js
1114
1114
  function make(compare) {
1115
1115
  return (self, that) => self === that ? 0 : compare(self, that);
1116
1116
  }
1117
1117
  var String2 = /* @__PURE__ */ make((self, that) => self < that ? -1 : 1);
1118
1118
 
1119
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Option.js
1119
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Option.js
1120
1120
  var none2 = () => none;
1121
1121
  var some2 = some;
1122
1122
  var isNone2 = isNone;
@@ -1126,7 +1126,7 @@ var orElse = /* @__PURE__ */ dual(2, (self, that) => isNone2(self) ? that() : se
1126
1126
  var fromNullishOr = (a) => a == null ? none2() : some2(a);
1127
1127
  var getOrUndefined = /* @__PURE__ */ getOrElse(constUndefined);
1128
1128
 
1129
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Result.js
1129
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Result.js
1130
1130
  var succeed2 = succeed;
1131
1131
  var fail2 = fail;
1132
1132
  var isFailure2 = isFailure;
@@ -1134,7 +1134,7 @@ var isSuccess2 = isSuccess;
1134
1134
  var map = /* @__PURE__ */ dual(2, (self, f) => isSuccess2(self) ? succeed2(f(self.success)) : fail2(self.failure));
1135
1135
  var getOrElse2 = /* @__PURE__ */ dual(2, (self, onFailure) => isFailure2(self) ? onFailure(self.failure) : self.success);
1136
1136
 
1137
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Record.js
1137
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Record.js
1138
1138
  var map2 = /* @__PURE__ */ dual(2, (self, f) => {
1139
1139
  const out = {
1140
1140
  ...self
@@ -1146,7 +1146,7 @@ var map2 = /* @__PURE__ */ dual(2, (self, f) => {
1146
1146
  });
1147
1147
  var keys = (self) => Object.keys(self);
1148
1148
 
1149
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Array.js
1149
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Array.js
1150
1150
  var Array2 = globalThis.Array;
1151
1151
  var fromIterable = (collection) => Array2.isArray(collection) ? collection : Array2.from(collection);
1152
1152
  var append = /* @__PURE__ */ dual(2, (self, last) => [...self, last]);
@@ -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);
@@ -4098,33 +4121,33 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
4098
4121
  ),
4099
4122
  ([Identifier, Service]) => ({ Identifier, Service })
4100
4123
  );
4101
- const serviceVarianceStruct = (type, atLocation) => map4(
4102
- all(
4103
- varianceStructInvariantType(type, atLocation, "_Identifier"),
4104
- varianceStructInvariantType(type, atLocation, "_Service")
4105
- ),
4106
- ([Identifier, Service]) => ({ Identifier, Service })
4107
- );
4108
4124
  const serviceType = cachedBy(
4109
4125
  fn("TypeParser.serviceType")(function* (type, atLocation) {
4126
+ if (supportedEffect() !== "v4") return yield* typeParserIssue("v4 only");
4110
4127
  yield* pipeableType(type, atLocation);
4111
- const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
4112
- (_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional) && _.valueDeclaration
4113
- );
4114
- if (propertiesSymbols.length === 0) {
4115
- return yield* typeParserIssue("Type has no tag variance struct", type, atLocation);
4128
+ const typeIdSymbol = typeChecker.getPropertyOfType(type, "~effect/ServiceMap/Service");
4129
+ if (!typeIdSymbol) {
4130
+ return yield* typeParserIssue("Type has no service key type id", type, atLocation);
4116
4131
  }
4117
- propertiesSymbols.sort((a, b) => ts.symbolName(b).indexOf("TypeId") - ts.symbolName(a).indexOf("TypeId"));
4118
- return yield* firstSuccessOf(propertiesSymbols.map((propertySymbol) => {
4119
- const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
4120
- return serviceVarianceStruct(propertyType, atLocation);
4121
- }));
4132
+ const identifierSymbol = typeChecker.getPropertyOfType(type, "Identifier");
4133
+ if (!identifierSymbol) {
4134
+ return yield* typeParserIssue("Type has no 'Identifier' property", type, atLocation);
4135
+ }
4136
+ const serviceSymbol = typeChecker.getPropertyOfType(type, "Service");
4137
+ if (!serviceSymbol) {
4138
+ return yield* typeParserIssue("Type has no 'Service' property", type, atLocation);
4139
+ }
4140
+ return {
4141
+ Identifier: typeChecker.getTypeOfSymbolAtLocation(identifierSymbol, atLocation),
4142
+ Service: typeChecker.getTypeOfSymbolAtLocation(serviceSymbol, atLocation)
4143
+ };
4122
4144
  }),
4123
4145
  "TypeParser.serviceType",
4124
4146
  (type) => type
4125
4147
  );
4126
4148
  const contextTag = cachedBy(
4127
4149
  fn("TypeParser.contextTag")(function* (type, atLocation) {
4150
+ if (supportedEffect() !== "v3") return yield* typeParserIssue("v3 only");
4128
4151
  yield* pipeableType(type, atLocation);
4129
4152
  const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
4130
4153
  (_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional) && _.valueDeclaration
@@ -4265,6 +4288,19 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
4265
4288
  "TypeParser.promiseLike",
4266
4289
  (type) => type
4267
4290
  );
4291
+ const promiseType = cachedBy(
4292
+ function(type, atLocation) {
4293
+ const promiseSymbol = typeChecker.resolveName("Promise", void 0, ts.SymbolFlags.Type, false);
4294
+ if (!promiseSymbol) return typeParserIssue("global Promise type not found", type, atLocation);
4295
+ const globalPromiseType = typeChecker.getDeclaredTypeOfSymbol(promiseSymbol);
4296
+ if (type === globalPromiseType || "target" in type && type.target === globalPromiseType || typeChecker.isTypeAssignableTo(type, globalPromiseType)) {
4297
+ return succeed3(type);
4298
+ }
4299
+ return typeParserIssue("type is not a Promise", type, atLocation);
4300
+ },
4301
+ "TypeParser.promiseType",
4302
+ (type) => type
4303
+ );
4268
4304
  const extendsSchemaClass = cachedBy(
4269
4305
  fn("TypeParser.extendsSchemaClass")(function* (atLocation) {
4270
4306
  if (!atLocation.name) {
@@ -5262,6 +5298,7 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
5262
5298
  isServiceMapTypeSourceFile,
5263
5299
  isNodeReferenceToServiceMapModuleApi,
5264
5300
  effectType,
5301
+ streamType,
5265
5302
  strictEffectType,
5266
5303
  layerType,
5267
5304
  fiberType,
@@ -5283,6 +5320,7 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
5283
5320
  singleArgCall,
5284
5321
  scopeType,
5285
5322
  promiseLike,
5323
+ promiseType,
5286
5324
  extendsEffectTag,
5287
5325
  extendsEffectService,
5288
5326
  extendsServiceMapService,
@@ -5411,6 +5449,37 @@ var anyUnknownInErrorContext = createDiagnostic({
5411
5449
  })
5412
5450
  });
5413
5451
 
5452
+ // src/diagnostics/asyncFunction.ts
5453
+ var asyncFunction = createDiagnostic({
5454
+ name: "asyncFunction",
5455
+ code: 69,
5456
+ description: "Warns when declaring async functions and suggests using Effect values and Effect.gen for async control flow",
5457
+ group: "effectNative",
5458
+ severity: "off",
5459
+ fixable: false,
5460
+ supportedEffect: ["v3", "v4"],
5461
+ apply: fn("asyncFunction.apply")(function* (sourceFile, report) {
5462
+ const ts = yield* service(TypeScriptApi);
5463
+ const hasAsyncModifier = (node) => ts.getModifiers(node)?.some((modifier) => modifier.kind === ts.SyntaxKind.AsyncKeyword) === true;
5464
+ const visit = (node) => {
5465
+ if (!ts.isFunctionDeclaration(node) && !ts.isFunctionExpression(node) && !ts.isArrowFunction(node) && !ts.isMethodDeclaration(node)) {
5466
+ ts.forEachChild(node, visit);
5467
+ return void 0;
5468
+ }
5469
+ if (hasAsyncModifier(node)) {
5470
+ report({
5471
+ location: node,
5472
+ messageText: "This code declares an async function, consider representing this async control flow with Effect values and `Effect.gen`.",
5473
+ fixes: []
5474
+ });
5475
+ }
5476
+ ts.forEachChild(node, visit);
5477
+ return void 0;
5478
+ };
5479
+ ts.forEachChild(sourceFile, visit);
5480
+ })
5481
+ });
5482
+
5414
5483
  // src/diagnostics/catchAllToMapError.ts
5415
5484
  var catchAllToMapError = createDiagnostic({
5416
5485
  name: "catchAllToMapError",
@@ -5489,7 +5558,7 @@ var catchAllToMapError = createDiagnostic({
5489
5558
  const { failArg, failCall } = failCallInfo;
5490
5559
  report({
5491
5560
  location: transformation.callee,
5492
- messageText: `You can use Effect.mapError instead of Effect.${catchAllName} + Effect.fail to transform the error type.`,
5561
+ messageText: `\`Effect.mapError\` expresses the same error-type transformation more directly than \`Effect.${catchAllName}\` followed by \`Effect.fail\`.`,
5493
5562
  fixes: [{
5494
5563
  fixName: "catchAllToMapError_fix",
5495
5564
  description: "Replace with Effect.mapError",
@@ -5553,7 +5622,7 @@ var catchUnfailableEffect = createDiagnostic({
5553
5622
  if (E.flags & ts.TypeFlags.Never) {
5554
5623
  report({
5555
5624
  location: transformation.callee,
5556
- messageText: `Looks like the previous effect never fails, so probably this error handling will never be triggered.`,
5625
+ messageText: "The previous Effect does not fail, so this error-handling branch will never run.",
5557
5626
  fixes: []
5558
5627
  });
5559
5628
  }
@@ -5616,7 +5685,7 @@ var classSelfMismatch = createDiagnostic({
5616
5685
  if (actualName !== expectedName) {
5617
5686
  report({
5618
5687
  location: selfTypeNode,
5619
- messageText: `Self type parameter should be '${expectedName}'`,
5688
+ messageText: `The \`Self\` type parameter for this class should be \`${expectedName}\`.`,
5620
5689
  fixes: [{
5621
5690
  fixName: "classSelfMismatch_fix",
5622
5691
  description: `Replace '${actualName}' with '${expectedName}'`,
@@ -5639,6 +5708,59 @@ var classSelfMismatch = createDiagnostic({
5639
5708
  })
5640
5709
  });
5641
5710
 
5711
+ // src/diagnostics/cryptoRandomUUIDInEffect.ts
5712
+ var makeCryptoRandomUUIDApply = (checkInEffect) => fn(`cryptoRandomUUID${checkInEffect ? "InEffect" : ""}.apply`)(function* (sourceFile, report) {
5713
+ const ts = yield* service(TypeScriptApi);
5714
+ const typeChecker = yield* service(TypeCheckerApi);
5715
+ const typeCheckerUtils = yield* service(TypeCheckerUtils);
5716
+ const typeParser = yield* service(TypeParser);
5717
+ const cryptoSymbol = typeChecker.resolveName("crypto", void 0, ts.SymbolFlags.Value, false);
5718
+ if (!cryptoSymbol) return;
5719
+ const nodeToVisit = [];
5720
+ const appendNodeToVisit = (node) => {
5721
+ nodeToVisit.push(node);
5722
+ return void 0;
5723
+ };
5724
+ ts.forEachChild(sourceFile, appendNodeToVisit);
5725
+ while (nodeToVisit.length > 0) {
5726
+ const node = nodeToVisit.shift();
5727
+ ts.forEachChild(node, appendNodeToVisit);
5728
+ if (!ts.isCallExpression(node) || !ts.isPropertyAccessExpression(node.expression) || ts.idText(node.expression.name) !== "randomUUID") continue;
5729
+ const symbol3 = typeChecker.getSymbolAtLocation(node.expression.expression);
5730
+ if (!symbol3) continue;
5731
+ if (typeCheckerUtils.resolveToGlobalSymbol(symbol3) !== cryptoSymbol) continue;
5732
+ const { inEffect } = yield* typeParser.findEnclosingScopes(node);
5733
+ if (inEffect !== checkInEffect) continue;
5734
+ report({
5735
+ location: node,
5736
+ messageText: checkInEffect ? "This Effect code uses `crypto.randomUUID()`, prefer the Effect `Random` module instead because it uses Effect-injected randomness rather than the `crypto` module behind the scenes." : "This code uses `crypto.randomUUID()`, prefer the Effect `Random` module instead because it uses Effect-injected randomness rather than the `crypto` module behind the scenes.",
5737
+ fixes: []
5738
+ });
5739
+ }
5740
+ });
5741
+ var cryptoRandomUUIDInEffect = createDiagnostic({
5742
+ name: "cryptoRandomUUIDInEffect",
5743
+ code: 67,
5744
+ description: "Warns when using crypto.randomUUID() inside Effect generators instead of the Effect Random module, which uses Effect-injected randomness rather than the crypto module behind the scenes",
5745
+ group: "effectNative",
5746
+ severity: "off",
5747
+ fixable: false,
5748
+ supportedEffect: ["v4"],
5749
+ apply: makeCryptoRandomUUIDApply(true)
5750
+ });
5751
+
5752
+ // src/diagnostics/cryptoRandomUUID.ts
5753
+ var cryptoRandomUUID = createDiagnostic({
5754
+ name: "cryptoRandomUUID",
5755
+ code: 66,
5756
+ description: "Warns when using crypto.randomUUID() outside Effect generators instead of the Effect Random module, which uses Effect-injected randomness rather than the crypto module behind the scenes",
5757
+ group: "effectNative",
5758
+ severity: "off",
5759
+ fixable: false,
5760
+ supportedEffect: ["v4"],
5761
+ apply: makeCryptoRandomUUIDApply(false)
5762
+ });
5763
+
5642
5764
  // src/core/KeyBuilder.ts
5643
5765
  var makeKeyBuilder = fn("KeyBuilder")(
5644
5766
  function* (sourceFile) {
@@ -5806,7 +5928,7 @@ var deterministicKeys = createDiagnostic({
5806
5928
  if (actualIdentifier !== expectedKey) {
5807
5929
  report({
5808
5930
  location: keyStringLiteral,
5809
- messageText: `Key should be '${expectedKey}'`,
5931
+ messageText: `This key does not match the deterministic key for this declaration. The expected key is \`${expectedKey}\`.`,
5810
5932
  fixes: [{
5811
5933
  fixName: "deterministicKeys_fix",
5812
5934
  description: `Replace '${actualIdentifier}' with '${expectedKey}'`,
@@ -5845,9 +5967,8 @@ var duplicatePackage = createDiagnostic({
5845
5967
  const versions = Object.keys(resolvedPackages[packageName]);
5846
5968
  report({
5847
5969
  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]))}.
5970
+ messageText: `Multiple versions of package \`${packageName}\` were detected: ${versions.join(", ")}. Package duplication can change runtime identity and type equality across Effect modules.
5971
+ If this is intentional, set the LSP config \`allowedDuplicatedPackages\` to ${JSON.stringify(options.allowedDuplicatedPackages.concat([packageName]))}.
5851
5972
 
5852
5973
  ${versions.map((version) => `- found ${version} at ${resolvedPackages[packageName][version]}`).join("\n")}`,
5853
5974
  fixes: []
@@ -5857,6 +5978,40 @@ ${versions.map((version) => `- found ${version} at ${resolvedPackages[packageNam
5857
5978
  })
5858
5979
  });
5859
5980
 
5981
+ // src/diagnostics/effectDoNotation.ts
5982
+ var effectDoNotation = createDiagnostic({
5983
+ name: "effectDoNotation",
5984
+ code: 73,
5985
+ description: "Suggests using Effect.gen or Effect.fn instead of the Effect.Do notation helpers",
5986
+ group: "style",
5987
+ severity: "off",
5988
+ fixable: false,
5989
+ supportedEffect: ["v3", "v4"],
5990
+ apply: fn("effectDoNotation.apply")(function* (sourceFile, report) {
5991
+ const ts = yield* service(TypeScriptApi);
5992
+ const typeParser = yield* service(TypeParser);
5993
+ const nodeToVisit = [];
5994
+ const appendNodeToVisit = (node) => {
5995
+ nodeToVisit.push(node);
5996
+ return void 0;
5997
+ };
5998
+ ts.forEachChild(sourceFile, appendNodeToVisit);
5999
+ while (nodeToVisit.length > 0) {
6000
+ const node = nodeToVisit.shift();
6001
+ const isReference = yield* orUndefined(typeParser.isNodeReferenceToEffectModuleApi("Do")(node));
6002
+ if (isReference) {
6003
+ report({
6004
+ location: node,
6005
+ messageText: "This uses the Effect do emulation. `Effect.gen` or `Effect.fn` achieve the same result with native JS scopes.",
6006
+ fixes: []
6007
+ });
6008
+ continue;
6009
+ }
6010
+ ts.forEachChild(node, appendNodeToVisit);
6011
+ }
6012
+ })
6013
+ });
6014
+
5860
6015
  // src/diagnostics/effectFnIife.ts
5861
6016
  var effectFnIife = createDiagnostic({
5862
6017
  name: "effectFnIife",
@@ -5955,7 +6110,7 @@ var effectFnIife = createDiagnostic({
5955
6110
  const traceExpressionText = traceExpression ? sourceFile.text.slice(traceExpression.pos, traceExpression.end) : void 0;
5956
6111
  report({
5957
6112
  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` : ``}.`,
6113
+ 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
6114
  fixes
5960
6115
  });
5961
6116
  }
@@ -6040,7 +6195,7 @@ var effectFnImplicitAny = createDiagnostic({
6040
6195
  const parameterName = getParameterName(ts, parameter.name);
6041
6196
  report({
6042
6197
  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.`,
6198
+ 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
6199
  fixes: []
6045
6200
  });
6046
6201
  }
@@ -6636,7 +6791,7 @@ var effectFnOpportunity = createDiagnostic({
6636
6791
  const expectedSignature = generateExpectedSignature();
6637
6792
  report({
6638
6793
  location: nameIdentifier ?? targetNode,
6639
- messageText: `Can be rewritten as a reusable function: ${expectedSignature}`,
6794
+ messageText: `This expression can be rewritten in the reusable function form \`${expectedSignature}\`.`,
6640
6795
  fixes
6641
6796
  });
6642
6797
  }
@@ -6803,6 +6958,43 @@ var effectInVoidSuccess = createDiagnostic({
6803
6958
  })
6804
6959
  });
6805
6960
 
6961
+ // src/diagnostics/effectMapFlatten.ts
6962
+ var effectMapFlatten = createDiagnostic({
6963
+ name: "effectMapFlatten",
6964
+ code: 74,
6965
+ description: "Suggests using Effect.flatMap instead of Effect.map followed by Effect.flatten in piping flows",
6966
+ group: "style",
6967
+ severity: "suggestion",
6968
+ fixable: false,
6969
+ supportedEffect: ["v3", "v4"],
6970
+ apply: fn("effectMapFlatten.apply")(function* (sourceFile, report) {
6971
+ const typeParser = yield* service(TypeParser);
6972
+ const flows = yield* typeParser.pipingFlows(false)(sourceFile);
6973
+ for (const flow2 of flows) {
6974
+ for (let index = 0; index < flow2.transformations.length - 1; index++) {
6975
+ const mapTransformation = flow2.transformations[index];
6976
+ const flattenTransformation = flow2.transformations[index + 1];
6977
+ if (!mapTransformation || !flattenTransformation || !mapTransformation?.args || flattenTransformation?.args || mapTransformation.kind !== "pipe" && mapTransformation.kind !== "pipeable" || flattenTransformation.kind !== mapTransformation.kind) {
6978
+ continue;
6979
+ }
6980
+ const isMapCall = yield* orUndefined(
6981
+ typeParser.isNodeReferenceToEffectModuleApi("map")(mapTransformation.callee)
6982
+ );
6983
+ const isFlattenCall = yield* orUndefined(
6984
+ typeParser.isNodeReferenceToEffectModuleApi("flatten")(flattenTransformation.callee)
6985
+ );
6986
+ if (isMapCall && isFlattenCall) {
6987
+ report({
6988
+ location: flattenTransformation.callee,
6989
+ messageText: "`Effect.map` + `Effect.flatten` is the same as `Effect.flatMap` that expresses the same steps more directly.",
6990
+ fixes: []
6991
+ });
6992
+ }
6993
+ }
6994
+ }
6995
+ })
6996
+ });
6997
+
6806
6998
  // src/diagnostics/effectMapVoid.ts
6807
6999
  var effectMapVoid = createDiagnostic({
6808
7000
  name: "effectMapVoid",
@@ -6848,7 +7040,7 @@ var effectMapVoid = createDiagnostic({
6848
7040
  if (isNone2(match2)) continue;
6849
7041
  report({
6850
7042
  location: node.expression,
6851
- messageText: "Effect.asVoid can be used instead to discard the success value",
7043
+ messageText: "This expression discards the success value through mapping. `Effect.asVoid` represents that form directly.",
6852
7044
  fixes: [{
6853
7045
  fixName: "effectMapVoid_fix",
6854
7046
  description: "Replace with Effect.asVoid",
@@ -6903,7 +7095,7 @@ var effectSucceedWithVoid = createDiagnostic({
6903
7095
  if (!tsUtils.isVoidExpression(argument)) continue;
6904
7096
  report({
6905
7097
  location: node,
6906
- messageText: "Effect.void can be used instead of Effect.succeed(undefined) or Effect.succeed(void 0)",
7098
+ messageText: "`Effect.void` represents the same outcome as `Effect.succeed(undefined)` or `Effect.succeed(void 0)`.",
6907
7099
  fixes: [{
6908
7100
  fixName: "effectSucceedWithVoid_fix",
6909
7101
  description: "Replace with Effect.void",
@@ -6965,7 +7157,7 @@ var extendsNativeError = createDiagnostic({
6965
7157
  if (isNativeError) {
6966
7158
  report({
6967
7159
  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.",
7160
+ messageText: "This class extends the native `Error` type directly. Untagged native errors lose distinction in the Effect failure channel.",
6969
7161
  fixes: []
6970
7162
  });
6971
7163
  }
@@ -7010,7 +7202,12 @@ var floatingEffect = createDiagnostic({
7010
7202
  if (!isFloatingExpression(node)) continue;
7011
7203
  const type = typeCheckerUtils.getTypeAtLocation(node.expression);
7012
7204
  if (!type) continue;
7013
- const effect = yield* option(typeParser.effectType(type, node.expression));
7205
+ const effect = yield* option(
7206
+ pipe(
7207
+ typeParser.effectType(type, node.expression),
7208
+ orElse2(() => typeParser.streamType(type, node.expression))
7209
+ )
7210
+ );
7014
7211
  if (isSome2(effect)) {
7015
7212
  const allowedFloatingEffects = yield* pipe(
7016
7213
  typeParser.fiberType(type, node.expression),
@@ -7019,10 +7216,9 @@ var floatingEffect = createDiagnostic({
7019
7216
  );
7020
7217
  if (isNone2(allowedFloatingEffects)) {
7021
7218
  const isStrictEffect = yield* option(typeParser.strictEffectType(type, node.expression));
7022
- const name = isSome2(isStrictEffect) ? "Effect" : "Effect-able " + typeChecker.typeToString(type);
7023
7219
  report({
7024
7220
  location: node,
7025
- messageText: `${name} must be yielded or assigned to a variable.`,
7221
+ 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
7222
  fixes: []
7027
7223
  });
7028
7224
  }
@@ -7066,6 +7262,7 @@ var genericEffectServices = createDiagnostic({
7066
7262
  for (const [type, reportAt] of typesToCheck) {
7067
7263
  yield* pipe(
7068
7264
  typeParser.contextTag(type, node),
7265
+ orElse2(() => typeParser.serviceType(type, node)),
7069
7266
  map4(() => {
7070
7267
  report({
7071
7268
  location: reportAt,
@@ -7117,7 +7314,7 @@ var makeGlobalConsoleApply = (checkInEffect) => fn(`globalConsole${checkInEffect
7117
7314
  if (inEffect !== checkInEffect) continue;
7118
7315
  report({
7119
7316
  location: node,
7120
- messageText: checkInEffect ? `Prefer using ${alternative} instead of console.${method} inside Effect generators.` : `Prefer using ${alternative} instead of console.${method}.`,
7317
+ 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
7318
  fixes: []
7122
7319
  });
7123
7320
  }
@@ -7166,10 +7363,10 @@ var makeGlobalDateApply = (checkInEffect) => fn(`globalDate${checkInEffect ? "In
7166
7363
  let objectNode;
7167
7364
  if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.idText(node.expression.name) === "now") {
7168
7365
  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().";
7366
+ 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
7367
  } else if (ts.isNewExpression(node)) {
7171
7368
  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().";
7369
+ 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
7370
  }
7174
7371
  if (!messageText || !objectNode) continue;
7175
7372
  const symbol3 = typeChecker.getSymbolAtLocation(objectNode);
@@ -7252,7 +7449,7 @@ var globalErrorInEffectCatch = createDiagnostic({
7252
7449
  );
7253
7450
  report({
7254
7451
  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.`,
7452
+ 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
7453
  fixes: []
7257
7454
  });
7258
7455
  }
@@ -7332,7 +7529,7 @@ var makeGlobalFetchApply = (checkInEffect) => fn(`globalFetch${checkInEffect ? "
7332
7529
  if (!fetchSymbol) return;
7333
7530
  const effectVersion = typeParser.supportedEffect();
7334
7531
  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.`;
7532
+ 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
7533
  const nodeToVisit = [];
7337
7534
  const appendNodeToVisit = (node) => {
7338
7535
  nodeToVisit.push(node);
@@ -7405,7 +7602,7 @@ var makeGlobalRandomApply = (checkInEffect) => fn(`globalRandom${checkInEffect ?
7405
7602
  if (inEffect !== checkInEffect) continue;
7406
7603
  report({
7407
7604
  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().",
7605
+ 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
7606
  fixes: []
7410
7607
  });
7411
7608
  }
@@ -7436,12 +7633,12 @@ var globalRandom = createDiagnostic({
7436
7633
  // src/diagnostics/globalTimersInEffect.ts
7437
7634
  var timerAlternatives = {
7438
7635
  "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."
7636
+ inEffect: "This Effect code uses `setTimeout`, the corresponding timer API in this context is `Effect.sleep or Schedule` from Effect.",
7637
+ outsideEffect: "This code uses `setTimeout`, the corresponding Effect timer API is `Effect.sleep or Schedule` from Effect."
7441
7638
  },
7442
7639
  "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."
7640
+ inEffect: "This Effect code uses `setInterval`, the corresponding timer API in this context is `Schedule or Effect.repeat` from Effect.",
7641
+ outsideEffect: "This code uses `setInterval`, the corresponding Effect timer API is `Schedule or Effect.repeat` from Effect."
7445
7642
  }
7446
7643
  };
7447
7644
  var makeGlobalTimersApply = (checkInEffect) => fn(`globalTimers${checkInEffect ? "InEffect" : ""}.apply`)(function* (sourceFile, report) {
@@ -7683,7 +7880,7 @@ var instanceOfSchema = createDiagnostic({
7683
7880
  if (isSchemaType._tag === "Some") {
7684
7881
  report({
7685
7882
  location: node,
7686
- messageText: "Consider using Schema.is instead of instanceof for Effect Schema types.",
7883
+ messageText: "This code uses `instanceof` with an Effect Schema type. `Schema.is` is the schema-aware runtime check for this case.",
7687
7884
  fixes: [{
7688
7885
  fixName: "instanceOfSchema_fix",
7689
7886
  description: "Replace with Schema.is",
@@ -7829,6 +8026,55 @@ var layerMergeAllWithDependencies = createDiagnostic({
7829
8026
  })
7830
8027
  });
7831
8028
 
8029
+ // src/diagnostics/lazyPromiseInEffectSync.ts
8030
+ var lazyPromiseInEffectSync = createDiagnostic({
8031
+ name: "lazyPromiseInEffectSync",
8032
+ code: 70,
8033
+ description: "Warns when Effect.sync lazily returns a Promise instead of using an async Effect constructor",
8034
+ group: "antipattern",
8035
+ severity: "warning",
8036
+ fixable: false,
8037
+ supportedEffect: ["v3", "v4"],
8038
+ apply: fn("lazyPromiseInEffectSync.apply")(function* (sourceFile, report) {
8039
+ const ts = yield* service(TypeScriptApi);
8040
+ const typeChecker = yield* service(TypeCheckerApi);
8041
+ const typeCheckerUtils = yield* service(TypeCheckerUtils);
8042
+ const typeParser = yield* service(TypeParser);
8043
+ const nodeToVisit = [];
8044
+ const appendNodeToVisit = (node) => {
8045
+ nodeToVisit.push(node);
8046
+ return void 0;
8047
+ };
8048
+ ts.forEachChild(sourceFile, appendNodeToVisit);
8049
+ while (nodeToVisit.length > 0) {
8050
+ const node = nodeToVisit.shift();
8051
+ ts.forEachChild(node, appendNodeToVisit);
8052
+ if (!ts.isCallExpression(node)) continue;
8053
+ const isSyncCall = yield* orUndefined(
8054
+ typeParser.isNodeReferenceToEffectModuleApi("sync")(node.expression)
8055
+ );
8056
+ if (!isSyncCall) continue;
8057
+ const lazyArg = node.arguments[0];
8058
+ if (!lazyArg) continue;
8059
+ const lazyArgType = typeCheckerUtils.getTypeAtLocation(lazyArg);
8060
+ if (!lazyArgType) continue;
8061
+ const entries = typeCheckerUtils.unrollUnionMembers(lazyArgType).flatMap(
8062
+ (member) => typeChecker.getSignaturesOfType(member, ts.SignatureKind.Call).map(
8063
+ (signature) => typeParser.promiseType(typeChecker.getReturnTypeOfSignature(signature), lazyArg)
8064
+ )
8065
+ );
8066
+ if (entries.length === 0) continue;
8067
+ const promiseReturn = yield* orUndefined(firstSuccessOf(entries));
8068
+ if (!promiseReturn) continue;
8069
+ report({
8070
+ location: lazyArg,
8071
+ messageText: "This `Effect.sync` thunk returns a Promise. Use `Effect.promise` or `Effect.tryPromise` to represent async work.",
8072
+ fixes: []
8073
+ });
8074
+ }
8075
+ })
8076
+ });
8077
+
7832
8078
  // src/diagnostics/leakingRequirements.ts
7833
8079
  var leakingRequirements = createDiagnostic({
7834
8080
  name: "leakingRequirements",
@@ -7953,7 +8199,7 @@ var leakingRequirements = createDiagnostic({
7953
8199
  location: node,
7954
8200
  messageText: `Methods of this Service require \`${requirementsStr}\` from every caller.
7955
8201
 
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.
8202
+ The requirement becomes part of the public service surface instead of remaining internal to Layer implementation.
7957
8203
 
7958
8204
  Resolve these dependencies at Layer creation and provide them to each method, so the service's type reflects its purpose, not its implementation.
7959
8205
 
@@ -8150,7 +8396,7 @@ var missedPipeableOpportunity = createDiagnostic({
8150
8396
  ).trim() : "";
8151
8397
  report({
8152
8398
  location: flow2.node,
8153
- messageText: `Nested function calls can be converted to pipeable style for better readability; consider using ${subjectText}.pipe(...) instead.`,
8399
+ 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
8400
  fixes: [{
8155
8401
  fixName: "missedPipeableOpportunity_fix",
8156
8402
  description: "Convert to pipe style",
@@ -8231,7 +8477,7 @@ var missingEffectContext = createDiagnostic({
8231
8477
  (missingTypes) => missingTypes.length > 0 ? report(
8232
8478
  {
8233
8479
  location: node,
8234
- messageText: `Missing '${sortTypes(missingTypes).map((_) => typeChecker.typeToString(_)).join(" | ")}' in the expected Effect context.`,
8480
+ messageText: `This Effect requires a service that is missing from the expected Effect context: \`${sortTypes(missingTypes).map((_) => typeChecker.typeToString(_)).join(" | ")}\`.`,
8235
8481
  fixes: []
8236
8482
  }
8237
8483
  ) : void 0
@@ -8582,7 +8828,7 @@ var missingReturnYieldStar = createDiagnostic({
8582
8828
  }];
8583
8829
  report({
8584
8830
  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.`,
8831
+ messageText: "This Effect never succeeds; using `return yield*` preserves a definitive generator exit point for type narrowing and tooling support.",
8586
8832
  fixes: fix
8587
8833
  });
8588
8834
  }
@@ -8638,7 +8884,7 @@ var missingStarInYieldEffectGen = createDiagnostic({
8638
8884
  brokenGenerators.forEach(
8639
8885
  (pos) => report({
8640
8886
  location: { pos, end: pos + "function".length },
8641
- messageText: `Seems like you used yield instead of yield* inside this Effect.gen.`,
8887
+ messageText: "This uses `yield` for an `Effect` value. `yield*` is the Effect-aware form in this context.",
8642
8888
  fixes: []
8643
8889
  })
8644
8890
  );
@@ -8660,7 +8906,7 @@ var missingStarInYieldEffectGen = createDiagnostic({
8660
8906
  }] : [];
8661
8907
  report({
8662
8908
  location: node,
8663
- messageText: `When yielding Effects inside Effect.gen, you should use yield* instead of yield.`,
8909
+ messageText: "This uses `yield` for an `Effect` value. `yield*` is the Effect-aware form in this context.",
8664
8910
  fixes: fix
8665
8911
  });
8666
8912
  });
@@ -8728,7 +8974,7 @@ var multipleEffectProvide = createDiagnostic({
8728
8974
  if (chunk.length < 2) continue;
8729
8975
  report({
8730
8976
  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.",
8977
+ 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
8978
  fixes: [{
8733
8979
  fixName: "multipleEffectProvide_fix",
8734
8980
  description: "Combine into a single provide",
@@ -8762,6 +9008,74 @@ var multipleEffectProvide = createDiagnostic({
8762
9008
  })
8763
9009
  });
8764
9010
 
9011
+ // src/diagnostics/nestedEffectGenYield.ts
9012
+ var nestedEffectGenYield = createDiagnostic({
9013
+ name: "nestedEffectGenYield",
9014
+ code: 71,
9015
+ description: "Warns when yielding a nested bare Effect.gen inside an existing Effect generator context",
9016
+ group: "style",
9017
+ severity: "off",
9018
+ fixable: false,
9019
+ supportedEffect: ["v3", "v4"],
9020
+ apply: fn("nestedEffectGenYield.apply")(function* (sourceFile, report) {
9021
+ const ts = yield* service(TypeScriptApi);
9022
+ const typeParser = yield* service(TypeParser);
9023
+ const nodeToVisit = [];
9024
+ const appendNodeToVisit = (node) => {
9025
+ nodeToVisit.push(node);
9026
+ return void 0;
9027
+ };
9028
+ ts.forEachChild(sourceFile, appendNodeToVisit);
9029
+ while (nodeToVisit.length > 0) {
9030
+ const node = nodeToVisit.shift();
9031
+ ts.forEachChild(node, appendNodeToVisit);
9032
+ if (!ts.isYieldExpression(node) || !node.asteriskToken || !node.expression) continue;
9033
+ const { inEffect } = yield* typeParser.findEnclosingScopes(node);
9034
+ if (!inEffect) continue;
9035
+ const bareNestedEffectGen = yield* orUndefined(typeParser.effectGen(node.expression));
9036
+ if (!bareNestedEffectGen) continue;
9037
+ report({
9038
+ location: node.expression,
9039
+ messageText: "This `yield*` is applied to a nested `Effect.gen(...)` that can be inlined in the parent Effect generator context.",
9040
+ fixes: []
9041
+ });
9042
+ }
9043
+ })
9044
+ });
9045
+
9046
+ // src/diagnostics/newPromise.ts
9047
+ var newPromise = createDiagnostic({
9048
+ name: "newPromise",
9049
+ code: 68,
9050
+ description: "Warns when constructing promises with new Promise instead of using Effect APIs",
9051
+ group: "effectNative",
9052
+ severity: "off",
9053
+ fixable: false,
9054
+ supportedEffect: ["v3", "v4"],
9055
+ apply: fn("newPromise.apply")(function* (sourceFile, report) {
9056
+ const ts = yield* service(TypeScriptApi);
9057
+ const typeChecker = yield* service(TypeCheckerApi);
9058
+ const typeCheckerUtils = yield* service(TypeCheckerUtils);
9059
+ const promiseSymbol = typeChecker.resolveName("Promise", void 0, ts.SymbolFlags.Value, false);
9060
+ if (!promiseSymbol) return;
9061
+ const visit = (node) => {
9062
+ if (ts.isNewExpression(node)) {
9063
+ const symbol3 = typeChecker.getSymbolAtLocation(node.expression);
9064
+ if (symbol3 && typeCheckerUtils.resolveToGlobalSymbol(symbol3) === promiseSymbol) {
9065
+ report({
9066
+ location: node,
9067
+ messageText: "This code constructs `new Promise(...)`, prefer Effect APIs such as `Effect.async`, `Effect.promise`, or `Effect.tryPromise` instead of manual Promise construction.",
9068
+ fixes: []
9069
+ });
9070
+ }
9071
+ }
9072
+ ts.forEachChild(node, visit);
9073
+ return void 0;
9074
+ };
9075
+ ts.forEachChild(sourceFile, visit);
9076
+ })
9077
+ });
9078
+
8765
9079
  // src/diagnostics/nodeBuiltinImport.ts
8766
9080
  var moduleAlternativesV3 = /* @__PURE__ */ new Map([
8767
9081
  ["fs", { alternative: "FileSystem", module: "fs", package: "@effect/platform" }],
@@ -8818,7 +9132,7 @@ var nodeBuiltinImport = createDiagnostic({
8818
9132
  if (match2) {
8819
9133
  report({
8820
9134
  location: statement.moduleSpecifier,
8821
- messageText: `Prefer using ${match2.alternative} from ${match2.package} instead of the Node.js '${match2.module}' module.`,
9135
+ messageText: `This module reference uses the \`${match2.module}\` module, the corresponding Effect API is \`${match2.alternative}\` from \`${match2.package}\`.`,
8822
9136
  fixes: []
8823
9137
  });
8824
9138
  }
@@ -8831,7 +9145,7 @@ var nodeBuiltinImport = createDiagnostic({
8831
9145
  if (match2) {
8832
9146
  report({
8833
9147
  location: arg,
8834
- messageText: `Prefer using ${match2.alternative} from ${match2.package} instead of the Node.js '${match2.module}' module.`,
9148
+ messageText: `This module reference uses the \`${match2.module}\` module, the corresponding Effect API is \`${match2.alternative}\` from \`${match2.package}\`.`,
8835
9149
  fixes: []
8836
9150
  });
8837
9151
  }
@@ -8885,7 +9199,7 @@ var nonObjectEffectServiceType = createDiagnostic({
8885
9199
  const propertyValue = property.initializer;
8886
9200
  const errorToReport = {
8887
9201
  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.",
9202
+ 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
9203
  fixes: []
8890
9204
  };
8891
9205
  if (propertyName === "succeed") {
@@ -9105,6 +9419,14 @@ var effectModuleMigrationDb = {
9105
9419
  "yieldNow": asUnchanged,
9106
9420
  "zip": asUnchanged,
9107
9421
  "zipWith": asUnchanged,
9422
+ "annotateLogsScoped": asUnchanged,
9423
+ "awaitAllChildren": asUnchanged,
9424
+ "bind": asUnchanged,
9425
+ "bindTo": asUnchanged,
9426
+ "Do": asUnchanged,
9427
+ "let": asUnchanged,
9428
+ "partition": asUnchanged,
9429
+ "validate": asUnchanged,
9108
9430
  // Renamed APIs (v3 name → v4 name)
9109
9431
  "catchAll": asRenamedSameBehaviour("catch"),
9110
9432
  "catchAllCause": asRenamedSameBehaviour("catchCause"),
@@ -9124,14 +9446,6 @@ var effectModuleMigrationDb = {
9124
9446
  "serviceOptional": asRenamedSameBehaviour("serviceOption"),
9125
9447
  "tapErrorCause": asRenamedSameBehaviour("tapCause"),
9126
9448
  // Removed APIs
9127
- "annotateLogsScoped": asUnchanged,
9128
- "awaitAllChildren": asUnchanged,
9129
- "bind": asUnchanged,
9130
- "bindTo": asUnchanged,
9131
- "Do": asUnchanged,
9132
- "let": asUnchanged,
9133
- "partition": asUnchanged,
9134
- "validate": asUnchanged,
9135
9449
  "catchSomeDefect": asRemoved(
9136
9450
  "Use Effect.catchDefect or Effect.matchCause to handle specific defects."
9137
9451
  ),
@@ -9647,7 +9961,7 @@ var outdatedApi = createDiagnostic({
9647
9961
  hasReported = true;
9648
9962
  report({
9649
9963
  location: propertyAccess.name,
9650
- messageText: `${propertyName} is an Effect v3 API, but the project is using Effect v4.`,
9964
+ 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
9965
  fixes: []
9652
9966
  });
9653
9967
  }
@@ -9690,7 +10004,7 @@ var outdatedApi = createDiagnostic({
9690
10004
  if (hasReported) {
9691
10005
  report({
9692
10006
  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.",
10007
+ 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
10008
  fixes: []
9695
10009
  });
9696
10010
  }
@@ -10935,7 +11249,7 @@ var overriddenSchemaConstructor = createDiagnostic({
10935
11249
  };
10936
11250
  report({
10937
11251
  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.",
11252
+ 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
11253
  fixes: (member.body ? [fixAsStaticNew] : []).concat([{
10940
11254
  fixName: "overriddenSchemaConstructor_fix",
10941
11255
  description: "Remove the constructor override",
@@ -11057,7 +11371,7 @@ var preferSchemaOverJson = createDiagnostic({
11057
11371
  if (isSome2(match2)) {
11058
11372
  report({
11059
11373
  location: match2.value,
11060
- messageText: "Consider using Effect Schema for JSON operations instead of JSON.parse/JSON.stringify",
11374
+ messageText: "This code uses `JSON.parse` or `JSON.stringify`. Effect Schema provides Effect-aware APIs for JSON parsing and stringifying.",
11061
11375
  fixes: []
11062
11376
  });
11063
11377
  }
@@ -11065,6 +11379,63 @@ var preferSchemaOverJson = createDiagnostic({
11065
11379
  })
11066
11380
  });
11067
11381
 
11382
+ // src/diagnostics/processEnvInEffect.ts
11383
+ var isEnvPropertyAccess = (tsApi, node) => tsApi.isPropertyAccessExpression(node) && tsApi.idText(node.name) === "env";
11384
+ var isProcessEnvMemberAccess = (tsApi, node) => (tsApi.isPropertyAccessExpression(node) || tsApi.isElementAccessExpression(node)) && isEnvPropertyAccess(tsApi, node.expression);
11385
+ var makeProcessEnvApply = (checkInEffect) => fn(`processEnv${checkInEffect ? "InEffect" : ""}.apply`)(function* (sourceFile, report) {
11386
+ const ts = yield* service(TypeScriptApi);
11387
+ const typeChecker = yield* service(TypeCheckerApi);
11388
+ const typeCheckerUtils = yield* service(TypeCheckerUtils);
11389
+ const typeParser = yield* service(TypeParser);
11390
+ const processSymbol = typeChecker.resolveName("process", void 0, ts.SymbolFlags.Value, false);
11391
+ if (!processSymbol) return;
11392
+ const nodeToVisit = [];
11393
+ const appendNodeToVisit = (node) => {
11394
+ nodeToVisit.push(node);
11395
+ return void 0;
11396
+ };
11397
+ ts.forEachChild(sourceFile, appendNodeToVisit);
11398
+ while (nodeToVisit.length > 0) {
11399
+ const node = nodeToVisit.shift();
11400
+ ts.forEachChild(node, appendNodeToVisit);
11401
+ if (!isProcessEnvMemberAccess(ts, node)) continue;
11402
+ const processNode = node.expression.expression;
11403
+ if (!ts.isIdentifier(processNode) || ts.idText(processNode) !== "process") continue;
11404
+ const symbol3 = typeChecker.getSymbolAtLocation(processNode);
11405
+ if (!symbol3) continue;
11406
+ if (typeCheckerUtils.resolveToGlobalSymbol(symbol3) !== processSymbol) continue;
11407
+ const { inEffect } = yield* typeParser.findEnclosingScopes(node);
11408
+ if (inEffect !== checkInEffect) continue;
11409
+ report({
11410
+ location: node,
11411
+ messageText: checkInEffect ? "This Effect code reads from `process.env`, environment configuration in Effect code is represented through `Config` from Effect." : "This code reads from `process.env`, environment configuration is represented through `Config` from Effect.",
11412
+ fixes: []
11413
+ });
11414
+ }
11415
+ });
11416
+ var processEnvInEffect = createDiagnostic({
11417
+ name: "processEnvInEffect",
11418
+ code: 65,
11419
+ description: "Warns when reading process.env inside Effect generators instead of using Effect Config",
11420
+ group: "effectNative",
11421
+ severity: "off",
11422
+ fixable: false,
11423
+ supportedEffect: ["v3", "v4"],
11424
+ apply: makeProcessEnvApply(true)
11425
+ });
11426
+
11427
+ // src/diagnostics/processEnv.ts
11428
+ var processEnv = createDiagnostic({
11429
+ name: "processEnv",
11430
+ code: 64,
11431
+ description: "Warns when reading process.env outside Effect generators instead of using Effect Config",
11432
+ group: "effectNative",
11433
+ severity: "off",
11434
+ fixable: false,
11435
+ supportedEffect: ["v3", "v4"],
11436
+ apply: makeProcessEnvApply(false)
11437
+ });
11438
+
11068
11439
  // src/diagnostics/redundantSchemaTagIdentifier.ts
11069
11440
  var redundantSchemaTagIdentifier = createDiagnostic({
11070
11441
  name: "redundantSchemaTagIdentifier",
@@ -11175,9 +11546,7 @@ var returnEffectInGen = createDiagnostic({
11175
11546
  }] : [];
11176
11547
  report({
11177
11548
  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.`,
11549
+ 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
11550
  fixes: fix
11182
11551
  });
11183
11552
  }),
@@ -11332,9 +11701,7 @@ var runEffectInsideEffect = createDiagnostic({
11332
11701
  );
11333
11702
  });
11334
11703
  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.`;
11704
+ 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
11705
  report({
11339
11706
  location: node.expression,
11340
11707
  messageText,
@@ -11347,7 +11714,7 @@ Consider extracting the Runtime by using for example Effect.runtime and then use
11347
11714
  } else {
11348
11715
  report({
11349
11716
  location: node.expression,
11350
- messageText: `Using ${nodeText} inside an Effect is not recommended. Effects inside generators can usually just be yielded.`,
11717
+ messageText: `\`${nodeText}\` is called inside an existing Effect context. Here, the inner Effect can be used directly.`,
11351
11718
  fixes: []
11352
11719
  });
11353
11720
  }
@@ -11402,7 +11769,7 @@ var schemaStructWithTag = createDiagnostic({
11402
11769
  const otherProperties = arg.properties.filter((prop) => prop !== tagProperty);
11403
11770
  report({
11404
11771
  location: node,
11405
- messageText: "Schema.Struct with a _tag field can be simplified to Schema.TaggedStruct to make the tag optional in the constructor.",
11772
+ 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
11773
  fixes: [{
11407
11774
  fixName: "schemaStructWithTag_fix",
11408
11775
  description: "Replace with Schema.TaggedStruct",
@@ -11495,7 +11862,7 @@ var schemaSyncInEffect = createDiagnostic({
11495
11862
  const effectMethodName = syncToEffectMethod[isSchemaSyncCall.value.methodName];
11496
11863
  report({
11497
11864
  location: node.expression,
11498
- messageText: `Using ${nodeText} inside an Effect generator is not recommended. Use Schema.${effectMethodName} instead to get properly typed error channel.`,
11865
+ messageText: `\`${nodeText}\` is used inside an Effect generator. \`Schema.${effectMethodName}\` preserves the typed Effect error channel for this operation without throwing.`,
11499
11866
  fixes: []
11500
11867
  });
11501
11868
  }
@@ -11555,7 +11922,7 @@ var schemaUnionOfLiterals = createDiagnostic({
11555
11922
  const schemaLiteralExpression = firstLiteralCall.expression;
11556
11923
  report({
11557
11924
  location: node,
11558
- messageText: "A Schema.Union of multiple Schema.Literal calls can be simplified to a single Schema.Literal call.",
11925
+ messageText: "This `Schema.Union` contains multiple `Schema.Literal` members and can be simplified to a single `Schema.Literal` call.",
11559
11926
  fixes: [{
11560
11927
  fixName: "schemaUnionOfLiterals_fix",
11561
11928
  description: "Replace with a single Schema.Literal call",
@@ -11618,8 +11985,7 @@ var scopeInLayerEffect = createDiagnostic({
11618
11985
  map4(
11619
11986
  () => report({
11620
11987
  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.`,
11988
+ messageText: "This layer construction leaves `Scope` in the requirement set. The scoped API removes `Scope` from the resulting requirements.",
11623
11989
  fixes: methodIdentifier ? [{
11624
11990
  fixName: "scopeInLayerEffect_scoped",
11625
11991
  description: "Use scoped for Layer creation",
@@ -11719,7 +12085,7 @@ var serviceNotAsClass = createDiagnostic({
11719
12085
  const shapeText = typeArgs.length > 0 ? typeArgs.map((t) => sourceFile.text.substring(ts.getTokenPosOfNode(t, sourceFile), t.end)).join(", ") : "Shape";
11720
12086
  report({
11721
12087
  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, "")}") {}`,
12088
+ 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
12089
  fixes: [{
11724
12090
  fixName: "serviceNotAsClass",
11725
12091
  description: `Convert to class declaration`,
@@ -11932,7 +12298,7 @@ var tryCatchInEffectGen = createDiagnostic({
11932
12298
  map4(() => {
11933
12299
  report({
11934
12300
  location: node,
11935
- messageText: `Avoid using try/catch inside Effect generators. Use Effect's error handling mechanisms instead (e.g. ${alternatives.join(", ")}).`,
12301
+ messageText: `This Effect generator contains \`try/catch\`; in this context, error handling is expressed with Effect APIs such as ${alternatives.join(", ")}).`,
11936
12302
  fixes: []
11937
12303
  });
11938
12304
  }),
@@ -11993,8 +12359,7 @@ var unknownInEffectCatch = createDiagnostic({
11993
12359
  );
11994
12360
  report({
11995
12361
  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.`,
12362
+ 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
12363
  fixes: []
11999
12364
  });
12000
12365
  }
@@ -12008,6 +12373,56 @@ Consider wrapping unknown errors into Effect's Data.TaggedError for example, or
12008
12373
  })
12009
12374
  });
12010
12375
 
12376
+ // src/diagnostics/unnecessaryArrowBlock.ts
12377
+ var unnecessaryArrowBlock = createDiagnostic({
12378
+ name: "unnecessaryArrowBlock",
12379
+ code: 72,
12380
+ description: "Suggests using a concise arrow body when the block only returns an expression",
12381
+ group: "style",
12382
+ severity: "off",
12383
+ fixable: true,
12384
+ supportedEffect: ["v3", "v4"],
12385
+ apply: fn("unnecessaryArrowBlock.apply")(function* (sourceFile, report) {
12386
+ const ts = yield* service(TypeScriptApi);
12387
+ const nodeToVisit = [];
12388
+ const appendNodeToVisit = (node) => {
12389
+ nodeToVisit.push(node);
12390
+ return void 0;
12391
+ };
12392
+ ts.forEachChild(sourceFile, appendNodeToVisit);
12393
+ while (nodeToVisit.length > 0) {
12394
+ const node = nodeToVisit.shift();
12395
+ ts.forEachChild(node, appendNodeToVisit);
12396
+ if (!ts.isArrowFunction(node) || !ts.isBlock(node.body)) continue;
12397
+ if (node.body.statements.length !== 1) continue;
12398
+ const [statement] = node.body.statements;
12399
+ if (!ts.isReturnStatement(statement) || !statement.expression) continue;
12400
+ const returnedExpression = statement.expression;
12401
+ report({
12402
+ location: node.body,
12403
+ messageText: "This arrow function block only returns an expression and can use a concise body.",
12404
+ fixes: [{
12405
+ fixName: "unnecessaryArrowBlock_fix",
12406
+ description: "Use a concise arrow body",
12407
+ apply: gen(function* () {
12408
+ const changeTracker = yield* service(ChangeTracker);
12409
+ const replacementNode = ts.factory.updateArrowFunction(
12410
+ node,
12411
+ node.modifiers,
12412
+ node.typeParameters,
12413
+ node.parameters,
12414
+ node.type,
12415
+ node.equalsGreaterThanToken,
12416
+ ts.factory.createParenthesizedExpression(returnedExpression)
12417
+ );
12418
+ changeTracker.replaceNode(sourceFile, node, replacementNode);
12419
+ })
12420
+ }]
12421
+ });
12422
+ }
12423
+ })
12424
+ });
12425
+
12011
12426
  // src/diagnostics/unnecessaryEffectGen.ts
12012
12427
  var unnecessaryEffectGen = createDiagnostic({
12013
12428
  name: "unnecessaryEffectGen",
@@ -12091,7 +12506,7 @@ var unnecessaryFailYieldableError = createDiagnostic({
12091
12506
  map4(
12092
12507
  () => report({
12093
12508
  location: node,
12094
- messageText: `This Effect.fail call uses a yieldable error type as argument. You can yield* the error directly instead.`,
12509
+ messageText: "This `yield* Effect.fail(...)` passes a yieldable error value. `yield*` represents that value directly without wrapping it in `Effect.fail`.",
12095
12510
  fixes: [{
12096
12511
  fixName: "unnecessaryFailYieldableError_fix",
12097
12512
  description: "Replace yield* Effect.fail with yield*",
@@ -12196,7 +12611,7 @@ var unnecessaryPipeChain = createDiagnostic({
12196
12611
  map4(({ innerCall, pipeCall }) => {
12197
12612
  report({
12198
12613
  location: node,
12199
- messageText: `Chained pipe calls can be simplified to a single pipe call`,
12614
+ messageText: "This expression contains chained `pipe` calls that can be simplified to a single `pipe` call.",
12200
12615
  fixes: [{
12201
12616
  fixName: "unnecessaryPipeChain_fix",
12202
12617
  description: "Rewrite as single pipe call",
@@ -12308,12 +12723,17 @@ var unsupportedServiceAccessors = createDiagnostic({
12308
12723
  var diagnostics = [
12309
12724
  outdatedApi,
12310
12725
  anyUnknownInErrorContext,
12726
+ asyncFunction,
12311
12727
  instanceOfSchema,
12312
12728
  catchAllToMapError,
12313
12729
  catchUnfailableEffect,
12314
12730
  classSelfMismatch,
12731
+ cryptoRandomUUID,
12732
+ cryptoRandomUUIDInEffect,
12315
12733
  duplicatePackage,
12734
+ effectDoNotation,
12316
12735
  effectFnImplicitAny,
12736
+ effectMapFlatten,
12317
12737
  effectGenUsesAdapter,
12318
12738
  missingEffectContext,
12319
12739
  missingEffectError,
@@ -12322,6 +12742,8 @@ var diagnostics = [
12322
12742
  floatingEffect,
12323
12743
  effectInFailure,
12324
12744
  missingStarInYieldEffectGen,
12745
+ newPromise,
12746
+ lazyPromiseInEffectSync,
12325
12747
  unnecessaryEffectGen,
12326
12748
  unnecessaryFailYieldableError,
12327
12749
  missingReturnYieldStar,
@@ -12330,6 +12752,8 @@ var diagnostics = [
12330
12752
  genericEffectServices,
12331
12753
  globalFetch,
12332
12754
  globalFetchInEffect,
12755
+ processEnv,
12756
+ processEnvInEffect,
12333
12757
  returnEffectInGen,
12334
12758
  tryCatchInEffectGen,
12335
12759
  importFromBarrel,
@@ -12347,6 +12771,8 @@ var diagnostics = [
12347
12771
  strictEffectProvide,
12348
12772
  unknownInEffectCatch,
12349
12773
  runEffectInsideEffect,
12774
+ nestedEffectGenYield,
12775
+ unnecessaryArrowBlock,
12350
12776
  schemaUnionOfLiterals,
12351
12777
  schemaStructWithTag,
12352
12778
  globalErrorInEffectCatch,