@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.
package/transform.js CHANGED
@@ -24,7 +24,7 @@ __export(transform_exports, {
24
24
  });
25
25
  module.exports = __toCommonJS(transform_exports);
26
26
 
27
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Pipeable.js
27
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Pipeable.js
28
28
  var pipeArguments = (self, args3) => {
29
29
  switch (args3.length) {
30
30
  case 0:
@@ -57,7 +57,7 @@ var pipeArguments = (self, args3) => {
57
57
  }
58
58
  };
59
59
 
60
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Function.js
60
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Function.js
61
61
  var dual = function(arity, body) {
62
62
  if (typeof arity === "function") {
63
63
  return function() {
@@ -105,7 +105,7 @@ function pipe(a, ...args3) {
105
105
  return pipeArguments(a, args3);
106
106
  }
107
107
 
108
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/internal/equal.js
108
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/internal/equal.js
109
109
  var getAllObjectKeys = (obj) => {
110
110
  const keys2 = new Set(Reflect.ownKeys(obj));
111
111
  if (obj.constructor === Object) return keys2;
@@ -128,7 +128,7 @@ var getAllObjectKeys = (obj) => {
128
128
  };
129
129
  var byReferenceInstances = /* @__PURE__ */ new WeakSet();
130
130
 
131
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Predicate.js
131
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Predicate.js
132
132
  function isString(input) {
133
133
  return typeof input === "string";
134
134
  }
@@ -149,7 +149,7 @@ function isObjectKeyword(input) {
149
149
  }
150
150
  var hasProperty = /* @__PURE__ */ dual(2, (self, property) => isObjectKeyword(self) && property in self);
151
151
 
152
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Hash.js
152
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Hash.js
153
153
  var symbol = "~effect/interfaces/Hash";
154
154
  var hash = (self) => {
155
155
  switch (typeof self) {
@@ -268,7 +268,7 @@ function withVisitedTracking(obj, fn2) {
268
268
  return result;
269
269
  }
270
270
 
271
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Equal.js
271
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Equal.js
272
272
  var symbol2 = "~effect/interfaces/Equal";
273
273
  function equals() {
274
274
  if (arguments.length === 1) {
@@ -430,10 +430,10 @@ var compareSets = /* @__PURE__ */ makeCompareSet(compareBoth);
430
430
  var isEqual = (u) => hasProperty(u, symbol2);
431
431
  var asEquivalence = () => equals;
432
432
 
433
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/internal/array.js
433
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/internal/array.js
434
434
  var isArrayNonEmpty = (self) => self.length > 0;
435
435
 
436
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Redactable.js
436
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Redactable.js
437
437
  var symbolRedactable = /* @__PURE__ */ Symbol.for("~effect/Inspectable/redactable");
438
438
  var isRedactable = (u) => hasProperty(u, symbolRedactable);
439
439
  function redact(u) {
@@ -452,7 +452,7 @@ var emptyServiceMap = {
452
452
  }
453
453
  };
454
454
 
455
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Formatter.js
455
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Formatter.js
456
456
  function format(input, options) {
457
457
  const space = options?.space ?? 0;
458
458
  const seen = /* @__PURE__ */ new WeakSet();
@@ -531,7 +531,7 @@ function safeToString(input) {
531
531
  }
532
532
  }
533
533
 
534
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Inspectable.js
534
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Inspectable.js
535
535
  var NodeInspectSymbol = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
536
536
  var toJson = (input) => {
537
537
  try {
@@ -575,7 +575,7 @@ var Class = class {
575
575
  }
576
576
  };
577
577
 
578
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Utils.js
578
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Utils.js
579
579
  var SingleShotGen = class _SingleShotGen {
580
580
  called = false;
581
581
  self;
@@ -618,7 +618,7 @@ var forced = {
618
618
  var isNotOptimizedAway = /* @__PURE__ */ standard[InternalTypeId](() => new Error().stack)?.includes(InternalTypeId) === true;
619
619
  var internalCall = isNotOptimizedAway ? standard[InternalTypeId] : forced[InternalTypeId];
620
620
 
621
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/internal/core.js
621
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/internal/core.js
622
622
  var EffectTypeId = `~effect/Effect`;
623
623
  var ExitTypeId = `~effect/Exit`;
624
624
  var effectVariance = {
@@ -965,7 +965,7 @@ var DoneVoid = {
965
965
  value: void 0
966
966
  };
967
967
 
968
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/internal/option.js
968
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/internal/option.js
969
969
  var TypeId = "~effect/data/Option";
970
970
  var CommonProto = {
971
971
  [TypeId]: {
@@ -1036,7 +1036,7 @@ var some = (value) => {
1036
1036
  return a;
1037
1037
  };
1038
1038
 
1039
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/internal/result.js
1039
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/internal/result.js
1040
1040
  var TypeId2 = "~effect/data/Result";
1041
1041
  var CommonProto2 = {
1042
1042
  [TypeId2]: {
@@ -1107,13 +1107,13 @@ var succeed = (success) => {
1107
1107
  return a;
1108
1108
  };
1109
1109
 
1110
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Order.js
1110
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Order.js
1111
1111
  function make(compare) {
1112
1112
  return (self, that) => self === that ? 0 : compare(self, that);
1113
1113
  }
1114
1114
  var String2 = /* @__PURE__ */ make((self, that) => self < that ? -1 : 1);
1115
1115
 
1116
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Option.js
1116
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Option.js
1117
1117
  var none2 = () => none;
1118
1118
  var some2 = some;
1119
1119
  var isNone2 = isNone;
@@ -1123,7 +1123,7 @@ var orElse = /* @__PURE__ */ dual(2, (self, that) => isNone2(self) ? that() : se
1123
1123
  var fromNullishOr = (a) => a == null ? none2() : some2(a);
1124
1124
  var getOrUndefined = /* @__PURE__ */ getOrElse(constUndefined);
1125
1125
 
1126
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Result.js
1126
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Result.js
1127
1127
  var succeed2 = succeed;
1128
1128
  var fail2 = fail;
1129
1129
  var isFailure2 = isFailure;
@@ -1131,7 +1131,7 @@ var isSuccess2 = isSuccess;
1131
1131
  var map = /* @__PURE__ */ dual(2, (self, f) => isSuccess2(self) ? succeed2(f(self.success)) : fail2(self.failure));
1132
1132
  var getOrElse2 = /* @__PURE__ */ dual(2, (self, onFailure) => isFailure2(self) ? onFailure(self.failure) : self.success);
1133
1133
 
1134
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Record.js
1134
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Record.js
1135
1135
  var map2 = /* @__PURE__ */ dual(2, (self, f) => {
1136
1136
  const out = {
1137
1137
  ...self
@@ -1143,7 +1143,7 @@ var map2 = /* @__PURE__ */ dual(2, (self, f) => {
1143
1143
  });
1144
1144
  var keys = (self) => Object.keys(self);
1145
1145
 
1146
- // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Array.js
1146
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.43/node_modules/effect/dist/Array.js
1147
1147
  var Array2 = globalThis.Array;
1148
1148
  var fromIterable = (collection) => Array2.isArray(collection) ? collection : Array2.from(collection);
1149
1149
  var append = /* @__PURE__ */ dual(2, (self, last) => [...self, last]);
@@ -3477,6 +3477,14 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
3477
3477
  ),
3478
3478
  ([A, E, R]) => ({ A, E, R })
3479
3479
  );
3480
+ const streamVarianceStruct = (type, atLocation) => map4(
3481
+ all(
3482
+ varianceStructCovariantType(type, atLocation, "_A"),
3483
+ varianceStructCovariantType(type, atLocation, "_E"),
3484
+ varianceStructCovariantType(type, atLocation, "_R")
3485
+ ),
3486
+ ([A, E, R]) => ({ A, E, R })
3487
+ );
3480
3488
  const layerVarianceStruct = (type, atLocation) => map4(
3481
3489
  all(
3482
3490
  varianceStructContravariantType(type, atLocation, "_ROut"),
@@ -3523,6 +3531,21 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
3523
3531
  "TypeParser.strictEffectType",
3524
3532
  (type) => type
3525
3533
  );
3534
+ const streamType = cachedBy(
3535
+ fn("TypeParser.streamType")(function* (type, atLocation) {
3536
+ if (supportedEffect() === "v3") {
3537
+ return yield* effectType(type, atLocation);
3538
+ }
3539
+ const typeIdSymbol = typeChecker.getPropertyOfType(type, "~effect/Stream");
3540
+ if (!typeIdSymbol) {
3541
+ return yield* typeParserIssue("Type is not a stream", type, atLocation);
3542
+ }
3543
+ const typeIdType = typeChecker.getTypeOfSymbolAtLocation(typeIdSymbol, atLocation);
3544
+ return yield* streamVarianceStruct(typeIdType, atLocation);
3545
+ }),
3546
+ "TypeParser.streamType",
3547
+ (type) => type
3548
+ );
3526
3549
  const isEffectTypeSourceFile = cachedBy(
3527
3550
  fn("TypeParser.isEffectTypeSourceFile")(function* (sourceFile) {
3528
3551
  const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
@@ -4094,33 +4117,33 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
4094
4117
  ),
4095
4118
  ([Identifier, Service]) => ({ Identifier, Service })
4096
4119
  );
4097
- const serviceVarianceStruct = (type, atLocation) => map4(
4098
- all(
4099
- varianceStructInvariantType(type, atLocation, "_Identifier"),
4100
- varianceStructInvariantType(type, atLocation, "_Service")
4101
- ),
4102
- ([Identifier, Service]) => ({ Identifier, Service })
4103
- );
4104
4120
  const serviceType = cachedBy(
4105
4121
  fn("TypeParser.serviceType")(function* (type, atLocation) {
4122
+ if (supportedEffect() !== "v4") return yield* typeParserIssue("v4 only");
4106
4123
  yield* pipeableType(type, atLocation);
4107
- const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
4108
- (_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional) && _.valueDeclaration
4109
- );
4110
- if (propertiesSymbols.length === 0) {
4111
- return yield* typeParserIssue("Type has no tag variance struct", type, atLocation);
4124
+ const typeIdSymbol = typeChecker.getPropertyOfType(type, "~effect/ServiceMap/Service");
4125
+ if (!typeIdSymbol) {
4126
+ return yield* typeParserIssue("Type has no service key type id", type, atLocation);
4112
4127
  }
4113
- propertiesSymbols.sort((a, b) => ts.symbolName(b).indexOf("TypeId") - ts.symbolName(a).indexOf("TypeId"));
4114
- return yield* firstSuccessOf(propertiesSymbols.map((propertySymbol) => {
4115
- const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
4116
- return serviceVarianceStruct(propertyType, atLocation);
4117
- }));
4128
+ const identifierSymbol = typeChecker.getPropertyOfType(type, "Identifier");
4129
+ if (!identifierSymbol) {
4130
+ return yield* typeParserIssue("Type has no 'Identifier' property", type, atLocation);
4131
+ }
4132
+ const serviceSymbol = typeChecker.getPropertyOfType(type, "Service");
4133
+ if (!serviceSymbol) {
4134
+ return yield* typeParserIssue("Type has no 'Service' property", type, atLocation);
4135
+ }
4136
+ return {
4137
+ Identifier: typeChecker.getTypeOfSymbolAtLocation(identifierSymbol, atLocation),
4138
+ Service: typeChecker.getTypeOfSymbolAtLocation(serviceSymbol, atLocation)
4139
+ };
4118
4140
  }),
4119
4141
  "TypeParser.serviceType",
4120
4142
  (type) => type
4121
4143
  );
4122
4144
  const contextTag = cachedBy(
4123
4145
  fn("TypeParser.contextTag")(function* (type, atLocation) {
4146
+ if (supportedEffect() !== "v3") return yield* typeParserIssue("v3 only");
4124
4147
  yield* pipeableType(type, atLocation);
4125
4148
  const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
4126
4149
  (_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional) && _.valueDeclaration
@@ -4261,6 +4284,19 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
4261
4284
  "TypeParser.promiseLike",
4262
4285
  (type) => type
4263
4286
  );
4287
+ const promiseType = cachedBy(
4288
+ function(type, atLocation) {
4289
+ const promiseSymbol = typeChecker.resolveName("Promise", void 0, ts.SymbolFlags.Type, false);
4290
+ if (!promiseSymbol) return typeParserIssue("global Promise type not found", type, atLocation);
4291
+ const globalPromiseType = typeChecker.getDeclaredTypeOfSymbol(promiseSymbol);
4292
+ if (type === globalPromiseType || "target" in type && type.target === globalPromiseType || typeChecker.isTypeAssignableTo(type, globalPromiseType)) {
4293
+ return succeed3(type);
4294
+ }
4295
+ return typeParserIssue("type is not a Promise", type, atLocation);
4296
+ },
4297
+ "TypeParser.promiseType",
4298
+ (type) => type
4299
+ );
4264
4300
  const extendsSchemaClass = cachedBy(
4265
4301
  fn("TypeParser.extendsSchemaClass")(function* (atLocation) {
4266
4302
  if (!atLocation.name) {
@@ -5258,6 +5294,7 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
5258
5294
  isServiceMapTypeSourceFile,
5259
5295
  isNodeReferenceToServiceMapModuleApi,
5260
5296
  effectType,
5297
+ streamType,
5261
5298
  strictEffectType,
5262
5299
  layerType,
5263
5300
  fiberType,
@@ -5279,6 +5316,7 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
5279
5316
  singleArgCall,
5280
5317
  scopeType,
5281
5318
  promiseLike,
5319
+ promiseType,
5282
5320
  extendsEffectTag,
5283
5321
  extendsEffectService,
5284
5322
  extendsServiceMapService,
@@ -5407,6 +5445,37 @@ var anyUnknownInErrorContext = createDiagnostic({
5407
5445
  })
5408
5446
  });
5409
5447
 
5448
+ // src/diagnostics/asyncFunction.ts
5449
+ var asyncFunction = createDiagnostic({
5450
+ name: "asyncFunction",
5451
+ code: 69,
5452
+ description: "Warns when declaring async functions and suggests using Effect values and Effect.gen for async control flow",
5453
+ group: "effectNative",
5454
+ severity: "off",
5455
+ fixable: false,
5456
+ supportedEffect: ["v3", "v4"],
5457
+ apply: fn("asyncFunction.apply")(function* (sourceFile, report) {
5458
+ const ts = yield* service(TypeScriptApi);
5459
+ const hasAsyncModifier = (node) => ts.getModifiers(node)?.some((modifier) => modifier.kind === ts.SyntaxKind.AsyncKeyword) === true;
5460
+ const visit = (node) => {
5461
+ if (!ts.isFunctionDeclaration(node) && !ts.isFunctionExpression(node) && !ts.isArrowFunction(node) && !ts.isMethodDeclaration(node)) {
5462
+ ts.forEachChild(node, visit);
5463
+ return void 0;
5464
+ }
5465
+ if (hasAsyncModifier(node)) {
5466
+ report({
5467
+ location: node,
5468
+ messageText: "This code declares an async function, consider representing this async control flow with Effect values and `Effect.gen`.",
5469
+ fixes: []
5470
+ });
5471
+ }
5472
+ ts.forEachChild(node, visit);
5473
+ return void 0;
5474
+ };
5475
+ ts.forEachChild(sourceFile, visit);
5476
+ })
5477
+ });
5478
+
5410
5479
  // src/diagnostics/catchAllToMapError.ts
5411
5480
  var catchAllToMapError = createDiagnostic({
5412
5481
  name: "catchAllToMapError",
@@ -5485,7 +5554,7 @@ var catchAllToMapError = createDiagnostic({
5485
5554
  const { failArg, failCall } = failCallInfo;
5486
5555
  report({
5487
5556
  location: transformation.callee,
5488
- messageText: `You can use Effect.mapError instead of Effect.${catchAllName} + Effect.fail to transform the error type.`,
5557
+ messageText: `\`Effect.mapError\` expresses the same error-type transformation more directly than \`Effect.${catchAllName}\` followed by \`Effect.fail\`.`,
5489
5558
  fixes: [{
5490
5559
  fixName: "catchAllToMapError_fix",
5491
5560
  description: "Replace with Effect.mapError",
@@ -5549,7 +5618,7 @@ var catchUnfailableEffect = createDiagnostic({
5549
5618
  if (E.flags & ts.TypeFlags.Never) {
5550
5619
  report({
5551
5620
  location: transformation.callee,
5552
- messageText: `Looks like the previous effect never fails, so probably this error handling will never be triggered.`,
5621
+ messageText: "The previous Effect does not fail, so this error-handling branch will never run.",
5553
5622
  fixes: []
5554
5623
  });
5555
5624
  }
@@ -5612,7 +5681,7 @@ var classSelfMismatch = createDiagnostic({
5612
5681
  if (actualName !== expectedName) {
5613
5682
  report({
5614
5683
  location: selfTypeNode,
5615
- messageText: `Self type parameter should be '${expectedName}'`,
5684
+ messageText: `The \`Self\` type parameter for this class should be \`${expectedName}\`.`,
5616
5685
  fixes: [{
5617
5686
  fixName: "classSelfMismatch_fix",
5618
5687
  description: `Replace '${actualName}' with '${expectedName}'`,
@@ -5635,6 +5704,59 @@ var classSelfMismatch = createDiagnostic({
5635
5704
  })
5636
5705
  });
5637
5706
 
5707
+ // src/diagnostics/cryptoRandomUUIDInEffect.ts
5708
+ var makeCryptoRandomUUIDApply = (checkInEffect) => fn(`cryptoRandomUUID${checkInEffect ? "InEffect" : ""}.apply`)(function* (sourceFile, report) {
5709
+ const ts = yield* service(TypeScriptApi);
5710
+ const typeChecker = yield* service(TypeCheckerApi);
5711
+ const typeCheckerUtils = yield* service(TypeCheckerUtils);
5712
+ const typeParser = yield* service(TypeParser);
5713
+ const cryptoSymbol = typeChecker.resolveName("crypto", void 0, ts.SymbolFlags.Value, false);
5714
+ if (!cryptoSymbol) return;
5715
+ const nodeToVisit = [];
5716
+ const appendNodeToVisit = (node) => {
5717
+ nodeToVisit.push(node);
5718
+ return void 0;
5719
+ };
5720
+ ts.forEachChild(sourceFile, appendNodeToVisit);
5721
+ while (nodeToVisit.length > 0) {
5722
+ const node = nodeToVisit.shift();
5723
+ ts.forEachChild(node, appendNodeToVisit);
5724
+ if (!ts.isCallExpression(node) || !ts.isPropertyAccessExpression(node.expression) || ts.idText(node.expression.name) !== "randomUUID") continue;
5725
+ const symbol3 = typeChecker.getSymbolAtLocation(node.expression.expression);
5726
+ if (!symbol3) continue;
5727
+ if (typeCheckerUtils.resolveToGlobalSymbol(symbol3) !== cryptoSymbol) continue;
5728
+ const { inEffect } = yield* typeParser.findEnclosingScopes(node);
5729
+ if (inEffect !== checkInEffect) continue;
5730
+ report({
5731
+ location: node,
5732
+ 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.",
5733
+ fixes: []
5734
+ });
5735
+ }
5736
+ });
5737
+ var cryptoRandomUUIDInEffect = createDiagnostic({
5738
+ name: "cryptoRandomUUIDInEffect",
5739
+ code: 67,
5740
+ 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",
5741
+ group: "effectNative",
5742
+ severity: "off",
5743
+ fixable: false,
5744
+ supportedEffect: ["v4"],
5745
+ apply: makeCryptoRandomUUIDApply(true)
5746
+ });
5747
+
5748
+ // src/diagnostics/cryptoRandomUUID.ts
5749
+ var cryptoRandomUUID = createDiagnostic({
5750
+ name: "cryptoRandomUUID",
5751
+ code: 66,
5752
+ 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",
5753
+ group: "effectNative",
5754
+ severity: "off",
5755
+ fixable: false,
5756
+ supportedEffect: ["v4"],
5757
+ apply: makeCryptoRandomUUIDApply(false)
5758
+ });
5759
+
5638
5760
  // src/core/KeyBuilder.ts
5639
5761
  var makeKeyBuilder = fn("KeyBuilder")(
5640
5762
  function* (sourceFile) {
@@ -5802,7 +5924,7 @@ var deterministicKeys = createDiagnostic({
5802
5924
  if (actualIdentifier !== expectedKey) {
5803
5925
  report({
5804
5926
  location: keyStringLiteral,
5805
- messageText: `Key should be '${expectedKey}'`,
5927
+ messageText: `This key does not match the deterministic key for this declaration. The expected key is \`${expectedKey}\`.`,
5806
5928
  fixes: [{
5807
5929
  fixName: "deterministicKeys_fix",
5808
5930
  description: `Replace '${actualIdentifier}' with '${expectedKey}'`,
@@ -5841,9 +5963,8 @@ var duplicatePackage = createDiagnostic({
5841
5963
  const versions = Object.keys(resolvedPackages[packageName]);
5842
5964
  report({
5843
5965
  location: sourceFile.statements[0],
5844
- messageText: `Package ${packageName} is referenced multiple times with different versions (${versions.join(", ")}) and may cause unexpected type errors.
5845
- Cleanup your dependencies and your package lockfile to avoid multiple instances of this package and reload the project.
5846
- If this is intended set the LSP config "allowedDuplicatedPackages" to ${JSON.stringify(options.allowedDuplicatedPackages.concat([packageName]))}.
5966
+ messageText: `Multiple versions of package \`${packageName}\` were detected: ${versions.join(", ")}. Package duplication can change runtime identity and type equality across Effect modules.
5967
+ If this is intentional, set the LSP config \`allowedDuplicatedPackages\` to ${JSON.stringify(options.allowedDuplicatedPackages.concat([packageName]))}.
5847
5968
 
5848
5969
  ${versions.map((version) => `- found ${version} at ${resolvedPackages[packageName][version]}`).join("\n")}`,
5849
5970
  fixes: []
@@ -5853,6 +5974,40 @@ ${versions.map((version) => `- found ${version} at ${resolvedPackages[packageNam
5853
5974
  })
5854
5975
  });
5855
5976
 
5977
+ // src/diagnostics/effectDoNotation.ts
5978
+ var effectDoNotation = createDiagnostic({
5979
+ name: "effectDoNotation",
5980
+ code: 73,
5981
+ description: "Suggests using Effect.gen or Effect.fn instead of the Effect.Do notation helpers",
5982
+ group: "style",
5983
+ severity: "off",
5984
+ fixable: false,
5985
+ supportedEffect: ["v3", "v4"],
5986
+ apply: fn("effectDoNotation.apply")(function* (sourceFile, report) {
5987
+ const ts = yield* service(TypeScriptApi);
5988
+ const typeParser = yield* service(TypeParser);
5989
+ const nodeToVisit = [];
5990
+ const appendNodeToVisit = (node) => {
5991
+ nodeToVisit.push(node);
5992
+ return void 0;
5993
+ };
5994
+ ts.forEachChild(sourceFile, appendNodeToVisit);
5995
+ while (nodeToVisit.length > 0) {
5996
+ const node = nodeToVisit.shift();
5997
+ const isReference = yield* orUndefined(typeParser.isNodeReferenceToEffectModuleApi("Do")(node));
5998
+ if (isReference) {
5999
+ report({
6000
+ location: node,
6001
+ messageText: "This uses the Effect do emulation. `Effect.gen` or `Effect.fn` achieve the same result with native JS scopes.",
6002
+ fixes: []
6003
+ });
6004
+ continue;
6005
+ }
6006
+ ts.forEachChild(node, appendNodeToVisit);
6007
+ }
6008
+ })
6009
+ });
6010
+
5856
6011
  // src/diagnostics/effectFnIife.ts
5857
6012
  var effectFnIife = createDiagnostic({
5858
6013
  name: "effectFnIife",
@@ -5951,7 +6106,7 @@ var effectFnIife = createDiagnostic({
5951
6106
  const traceExpressionText = traceExpression ? sourceFile.text.slice(traceExpression.pos, traceExpression.end) : void 0;
5952
6107
  report({
5953
6108
  location: node,
5954
- 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` : ``}.`,
6109
+ 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` : ``}.`,
5955
6110
  fixes
5956
6111
  });
5957
6112
  }
@@ -6036,7 +6191,7 @@ var effectFnImplicitAny = createDiagnostic({
6036
6191
  const parameterName = getParameterName(ts, parameter.name);
6037
6192
  report({
6038
6193
  location: parameter.name,
6039
- messageText: `Parameter '${parameterName}' implicitly has an 'any' type in Effect.fn/Effect.fnUntraced. Add an explicit type annotation or provide a contextual function type.`,
6194
+ 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.`,
6040
6195
  fixes: []
6041
6196
  });
6042
6197
  }
@@ -6632,7 +6787,7 @@ var effectFnOpportunity = createDiagnostic({
6632
6787
  const expectedSignature = generateExpectedSignature();
6633
6788
  report({
6634
6789
  location: nameIdentifier ?? targetNode,
6635
- messageText: `Can be rewritten as a reusable function: ${expectedSignature}`,
6790
+ messageText: `This expression can be rewritten in the reusable function form \`${expectedSignature}\`.`,
6636
6791
  fixes
6637
6792
  });
6638
6793
  }
@@ -6799,6 +6954,43 @@ var effectInVoidSuccess = createDiagnostic({
6799
6954
  })
6800
6955
  });
6801
6956
 
6957
+ // src/diagnostics/effectMapFlatten.ts
6958
+ var effectMapFlatten = createDiagnostic({
6959
+ name: "effectMapFlatten",
6960
+ code: 74,
6961
+ description: "Suggests using Effect.flatMap instead of Effect.map followed by Effect.flatten in piping flows",
6962
+ group: "style",
6963
+ severity: "suggestion",
6964
+ fixable: false,
6965
+ supportedEffect: ["v3", "v4"],
6966
+ apply: fn("effectMapFlatten.apply")(function* (sourceFile, report) {
6967
+ const typeParser = yield* service(TypeParser);
6968
+ const flows = yield* typeParser.pipingFlows(false)(sourceFile);
6969
+ for (const flow2 of flows) {
6970
+ for (let index = 0; index < flow2.transformations.length - 1; index++) {
6971
+ const mapTransformation = flow2.transformations[index];
6972
+ const flattenTransformation = flow2.transformations[index + 1];
6973
+ if (!mapTransformation || !flattenTransformation || !mapTransformation?.args || flattenTransformation?.args || mapTransformation.kind !== "pipe" && mapTransformation.kind !== "pipeable" || flattenTransformation.kind !== mapTransformation.kind) {
6974
+ continue;
6975
+ }
6976
+ const isMapCall = yield* orUndefined(
6977
+ typeParser.isNodeReferenceToEffectModuleApi("map")(mapTransformation.callee)
6978
+ );
6979
+ const isFlattenCall = yield* orUndefined(
6980
+ typeParser.isNodeReferenceToEffectModuleApi("flatten")(flattenTransformation.callee)
6981
+ );
6982
+ if (isMapCall && isFlattenCall) {
6983
+ report({
6984
+ location: flattenTransformation.callee,
6985
+ messageText: "`Effect.map` + `Effect.flatten` is the same as `Effect.flatMap` that expresses the same steps more directly.",
6986
+ fixes: []
6987
+ });
6988
+ }
6989
+ }
6990
+ }
6991
+ })
6992
+ });
6993
+
6802
6994
  // src/diagnostics/effectMapVoid.ts
6803
6995
  var effectMapVoid = createDiagnostic({
6804
6996
  name: "effectMapVoid",
@@ -6844,7 +7036,7 @@ var effectMapVoid = createDiagnostic({
6844
7036
  if (isNone2(match2)) continue;
6845
7037
  report({
6846
7038
  location: node.expression,
6847
- messageText: "Effect.asVoid can be used instead to discard the success value",
7039
+ messageText: "This expression discards the success value through mapping. `Effect.asVoid` represents that form directly.",
6848
7040
  fixes: [{
6849
7041
  fixName: "effectMapVoid_fix",
6850
7042
  description: "Replace with Effect.asVoid",
@@ -6899,7 +7091,7 @@ var effectSucceedWithVoid = createDiagnostic({
6899
7091
  if (!tsUtils.isVoidExpression(argument)) continue;
6900
7092
  report({
6901
7093
  location: node,
6902
- messageText: "Effect.void can be used instead of Effect.succeed(undefined) or Effect.succeed(void 0)",
7094
+ messageText: "`Effect.void` represents the same outcome as `Effect.succeed(undefined)` or `Effect.succeed(void 0)`.",
6903
7095
  fixes: [{
6904
7096
  fixName: "effectSucceedWithVoid_fix",
6905
7097
  description: "Replace with Effect.void",
@@ -6961,7 +7153,7 @@ var extendsNativeError = createDiagnostic({
6961
7153
  if (isNativeError) {
6962
7154
  report({
6963
7155
  location: node.name ?? typeExpression,
6964
- 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.",
7156
+ messageText: "This class extends the native `Error` type directly. Untagged native errors lose distinction in the Effect failure channel.",
6965
7157
  fixes: []
6966
7158
  });
6967
7159
  }
@@ -7006,7 +7198,12 @@ var floatingEffect = createDiagnostic({
7006
7198
  if (!isFloatingExpression(node)) continue;
7007
7199
  const type = typeCheckerUtils.getTypeAtLocation(node.expression);
7008
7200
  if (!type) continue;
7009
- const effect = yield* option(typeParser.effectType(type, node.expression));
7201
+ const effect = yield* option(
7202
+ pipe(
7203
+ typeParser.effectType(type, node.expression),
7204
+ orElse2(() => typeParser.streamType(type, node.expression))
7205
+ )
7206
+ );
7010
7207
  if (isSome2(effect)) {
7011
7208
  const allowedFloatingEffects = yield* pipe(
7012
7209
  typeParser.fiberType(type, node.expression),
@@ -7015,10 +7212,9 @@ var floatingEffect = createDiagnostic({
7015
7212
  );
7016
7213
  if (isNone2(allowedFloatingEffects)) {
7017
7214
  const isStrictEffect = yield* option(typeParser.strictEffectType(type, node.expression));
7018
- const name = isSome2(isStrictEffect) ? "Effect" : "Effect-able " + typeChecker.typeToString(type);
7019
7215
  report({
7020
7216
  location: node,
7021
- messageText: `${name} must be yielded or assigned to a variable.`,
7217
+ 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.`,
7022
7218
  fixes: []
7023
7219
  });
7024
7220
  }
@@ -7062,6 +7258,7 @@ var genericEffectServices = createDiagnostic({
7062
7258
  for (const [type, reportAt] of typesToCheck) {
7063
7259
  yield* pipe(
7064
7260
  typeParser.contextTag(type, node),
7261
+ orElse2(() => typeParser.serviceType(type, node)),
7065
7262
  map4(() => {
7066
7263
  report({
7067
7264
  location: reportAt,
@@ -7113,7 +7310,7 @@ var makeGlobalConsoleApply = (checkInEffect) => fn(`globalConsole${checkInEffect
7113
7310
  if (inEffect !== checkInEffect) continue;
7114
7311
  report({
7115
7312
  location: node,
7116
- messageText: checkInEffect ? `Prefer using ${alternative} instead of console.${method} inside Effect generators.` : `Prefer using ${alternative} instead of console.${method}.`,
7313
+ 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}\`.`,
7117
7314
  fixes: []
7118
7315
  });
7119
7316
  }
@@ -7162,10 +7359,10 @@ var makeGlobalDateApply = (checkInEffect) => fn(`globalDate${checkInEffect ? "In
7162
7359
  let objectNode;
7163
7360
  if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.idText(node.expression.name) === "now") {
7164
7361
  objectNode = node.expression.expression;
7165
- 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().";
7362
+ 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.";
7166
7363
  } else if (ts.isNewExpression(node)) {
7167
7364
  objectNode = node.expression;
7168
- messageText = checkInEffect ? "Prefer using DateTime from Effect instead of new Date() inside Effect generators." : "Prefer using DateTime from Effect instead of new Date().";
7365
+ 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.";
7169
7366
  }
7170
7367
  if (!messageText || !objectNode) continue;
7171
7368
  const symbol3 = typeChecker.getSymbolAtLocation(objectNode);
@@ -7248,7 +7445,7 @@ var globalErrorInEffectCatch = createDiagnostic({
7248
7445
  );
7249
7446
  report({
7250
7447
  location: node.expression,
7251
- 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.`,
7448
+ 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.`,
7252
7449
  fixes: []
7253
7450
  });
7254
7451
  }
@@ -7328,7 +7525,7 @@ var makeGlobalFetchApply = (checkInEffect) => fn(`globalFetch${checkInEffect ? "
7328
7525
  if (!fetchSymbol) return;
7329
7526
  const effectVersion = typeParser.supportedEffect();
7330
7527
  const packageName = effectVersion === "v3" ? "@effect/platform" : "effect/unstable/http";
7331
- 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.`;
7528
+ 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}\`.`;
7332
7529
  const nodeToVisit = [];
7333
7530
  const appendNodeToVisit = (node) => {
7334
7531
  nodeToVisit.push(node);
@@ -7401,7 +7598,7 @@ var makeGlobalRandomApply = (checkInEffect) => fn(`globalRandom${checkInEffect ?
7401
7598
  if (inEffect !== checkInEffect) continue;
7402
7599
  report({
7403
7600
  location: node,
7404
- 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().",
7601
+ 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.",
7405
7602
  fixes: []
7406
7603
  });
7407
7604
  }
@@ -7432,12 +7629,12 @@ var globalRandom = createDiagnostic({
7432
7629
  // src/diagnostics/globalTimersInEffect.ts
7433
7630
  var timerAlternatives = {
7434
7631
  "setTimeout": {
7435
- inEffect: "Prefer using Effect.sleep or Schedule from Effect instead of setTimeout inside Effect generators.",
7436
- outsideEffect: "Prefer using Effect.sleep or Schedule from Effect instead of setTimeout."
7632
+ inEffect: "This Effect code uses `setTimeout`, the corresponding timer API in this context is `Effect.sleep or Schedule` from Effect.",
7633
+ outsideEffect: "This code uses `setTimeout`, the corresponding Effect timer API is `Effect.sleep or Schedule` from Effect."
7437
7634
  },
7438
7635
  "setInterval": {
7439
- inEffect: "Prefer using Schedule or Effect.repeat from Effect instead of setInterval inside Effect generators.",
7440
- outsideEffect: "Prefer using Schedule or Effect.repeat from Effect instead of setInterval."
7636
+ inEffect: "This Effect code uses `setInterval`, the corresponding timer API in this context is `Schedule or Effect.repeat` from Effect.",
7637
+ outsideEffect: "This code uses `setInterval`, the corresponding Effect timer API is `Schedule or Effect.repeat` from Effect."
7441
7638
  }
7442
7639
  };
7443
7640
  var makeGlobalTimersApply = (checkInEffect) => fn(`globalTimers${checkInEffect ? "InEffect" : ""}.apply`)(function* (sourceFile, report) {
@@ -7679,7 +7876,7 @@ var instanceOfSchema = createDiagnostic({
7679
7876
  if (isSchemaType._tag === "Some") {
7680
7877
  report({
7681
7878
  location: node,
7682
- messageText: "Consider using Schema.is instead of instanceof for Effect Schema types.",
7879
+ messageText: "This code uses `instanceof` with an Effect Schema type. `Schema.is` is the schema-aware runtime check for this case.",
7683
7880
  fixes: [{
7684
7881
  fixName: "instanceOfSchema_fix",
7685
7882
  description: "Replace with Schema.is",
@@ -7825,6 +8022,55 @@ var layerMergeAllWithDependencies = createDiagnostic({
7825
8022
  })
7826
8023
  });
7827
8024
 
8025
+ // src/diagnostics/lazyPromiseInEffectSync.ts
8026
+ var lazyPromiseInEffectSync = createDiagnostic({
8027
+ name: "lazyPromiseInEffectSync",
8028
+ code: 70,
8029
+ description: "Warns when Effect.sync lazily returns a Promise instead of using an async Effect constructor",
8030
+ group: "antipattern",
8031
+ severity: "warning",
8032
+ fixable: false,
8033
+ supportedEffect: ["v3", "v4"],
8034
+ apply: fn("lazyPromiseInEffectSync.apply")(function* (sourceFile, report) {
8035
+ const ts = yield* service(TypeScriptApi);
8036
+ const typeChecker = yield* service(TypeCheckerApi);
8037
+ const typeCheckerUtils = yield* service(TypeCheckerUtils);
8038
+ const typeParser = yield* service(TypeParser);
8039
+ const nodeToVisit = [];
8040
+ const appendNodeToVisit = (node) => {
8041
+ nodeToVisit.push(node);
8042
+ return void 0;
8043
+ };
8044
+ ts.forEachChild(sourceFile, appendNodeToVisit);
8045
+ while (nodeToVisit.length > 0) {
8046
+ const node = nodeToVisit.shift();
8047
+ ts.forEachChild(node, appendNodeToVisit);
8048
+ if (!ts.isCallExpression(node)) continue;
8049
+ const isSyncCall = yield* orUndefined(
8050
+ typeParser.isNodeReferenceToEffectModuleApi("sync")(node.expression)
8051
+ );
8052
+ if (!isSyncCall) continue;
8053
+ const lazyArg = node.arguments[0];
8054
+ if (!lazyArg) continue;
8055
+ const lazyArgType = typeCheckerUtils.getTypeAtLocation(lazyArg);
8056
+ if (!lazyArgType) continue;
8057
+ const entries = typeCheckerUtils.unrollUnionMembers(lazyArgType).flatMap(
8058
+ (member) => typeChecker.getSignaturesOfType(member, ts.SignatureKind.Call).map(
8059
+ (signature) => typeParser.promiseType(typeChecker.getReturnTypeOfSignature(signature), lazyArg)
8060
+ )
8061
+ );
8062
+ if (entries.length === 0) continue;
8063
+ const promiseReturn = yield* orUndefined(firstSuccessOf(entries));
8064
+ if (!promiseReturn) continue;
8065
+ report({
8066
+ location: lazyArg,
8067
+ messageText: "This `Effect.sync` thunk returns a Promise. Use `Effect.promise` or `Effect.tryPromise` to represent async work.",
8068
+ fixes: []
8069
+ });
8070
+ }
8071
+ })
8072
+ });
8073
+
7828
8074
  // src/diagnostics/leakingRequirements.ts
7829
8075
  var leakingRequirements = createDiagnostic({
7830
8076
  name: "leakingRequirements",
@@ -7949,7 +8195,7 @@ var leakingRequirements = createDiagnostic({
7949
8195
  location: node,
7950
8196
  messageText: `Methods of this Service require \`${requirementsStr}\` from every caller.
7951
8197
 
7952
- 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.
8198
+ The requirement becomes part of the public service surface instead of remaining internal to Layer implementation.
7953
8199
 
7954
8200
  Resolve these dependencies at Layer creation and provide them to each method, so the service's type reflects its purpose, not its implementation.
7955
8201
 
@@ -8146,7 +8392,7 @@ var missedPipeableOpportunity = createDiagnostic({
8146
8392
  ).trim() : "";
8147
8393
  report({
8148
8394
  location: flow2.node,
8149
- messageText: `Nested function calls can be converted to pipeable style for better readability; consider using ${subjectText}.pipe(...) instead.`,
8395
+ 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.`,
8150
8396
  fixes: [{
8151
8397
  fixName: "missedPipeableOpportunity_fix",
8152
8398
  description: "Convert to pipe style",
@@ -8227,7 +8473,7 @@ var missingEffectContext = createDiagnostic({
8227
8473
  (missingTypes) => missingTypes.length > 0 ? report(
8228
8474
  {
8229
8475
  location: node,
8230
- messageText: `Missing '${sortTypes(missingTypes).map((_) => typeChecker.typeToString(_)).join(" | ")}' in the expected Effect context.`,
8476
+ messageText: `This Effect requires a service that is missing from the expected Effect context: \`${sortTypes(missingTypes).map((_) => typeChecker.typeToString(_)).join(" | ")}\`.`,
8231
8477
  fixes: []
8232
8478
  }
8233
8479
  ) : void 0
@@ -8578,7 +8824,7 @@ var missingReturnYieldStar = createDiagnostic({
8578
8824
  }];
8579
8825
  report({
8580
8826
  location: unwrapped,
8581
- 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.`,
8827
+ messageText: "This Effect never succeeds; using `return yield*` preserves a definitive generator exit point for type narrowing and tooling support.",
8582
8828
  fixes: fix
8583
8829
  });
8584
8830
  }
@@ -8634,7 +8880,7 @@ var missingStarInYieldEffectGen = createDiagnostic({
8634
8880
  brokenGenerators.forEach(
8635
8881
  (pos) => report({
8636
8882
  location: { pos, end: pos + "function".length },
8637
- messageText: `Seems like you used yield instead of yield* inside this Effect.gen.`,
8883
+ messageText: "This uses `yield` for an `Effect` value. `yield*` is the Effect-aware form in this context.",
8638
8884
  fixes: []
8639
8885
  })
8640
8886
  );
@@ -8656,7 +8902,7 @@ var missingStarInYieldEffectGen = createDiagnostic({
8656
8902
  }] : [];
8657
8903
  report({
8658
8904
  location: node,
8659
- messageText: `When yielding Effects inside Effect.gen, you should use yield* instead of yield.`,
8905
+ messageText: "This uses `yield` for an `Effect` value. `yield*` is the Effect-aware form in this context.",
8660
8906
  fixes: fix
8661
8907
  });
8662
8908
  });
@@ -8724,7 +8970,7 @@ var multipleEffectProvide = createDiagnostic({
8724
8970
  if (chunk.length < 2) continue;
8725
8971
  report({
8726
8972
  location: chunk[0].node,
8727
- messageText: "Avoid chaining Effect.provide calls, as this can lead to service lifecycle issues. Instead, merge layers and provide them in a single call.",
8973
+ 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.",
8728
8974
  fixes: [{
8729
8975
  fixName: "multipleEffectProvide_fix",
8730
8976
  description: "Combine into a single provide",
@@ -8758,6 +9004,74 @@ var multipleEffectProvide = createDiagnostic({
8758
9004
  })
8759
9005
  });
8760
9006
 
9007
+ // src/diagnostics/nestedEffectGenYield.ts
9008
+ var nestedEffectGenYield = createDiagnostic({
9009
+ name: "nestedEffectGenYield",
9010
+ code: 71,
9011
+ description: "Warns when yielding a nested bare Effect.gen inside an existing Effect generator context",
9012
+ group: "style",
9013
+ severity: "off",
9014
+ fixable: false,
9015
+ supportedEffect: ["v3", "v4"],
9016
+ apply: fn("nestedEffectGenYield.apply")(function* (sourceFile, report) {
9017
+ const ts = yield* service(TypeScriptApi);
9018
+ const typeParser = yield* service(TypeParser);
9019
+ const nodeToVisit = [];
9020
+ const appendNodeToVisit = (node) => {
9021
+ nodeToVisit.push(node);
9022
+ return void 0;
9023
+ };
9024
+ ts.forEachChild(sourceFile, appendNodeToVisit);
9025
+ while (nodeToVisit.length > 0) {
9026
+ const node = nodeToVisit.shift();
9027
+ ts.forEachChild(node, appendNodeToVisit);
9028
+ if (!ts.isYieldExpression(node) || !node.asteriskToken || !node.expression) continue;
9029
+ const { inEffect } = yield* typeParser.findEnclosingScopes(node);
9030
+ if (!inEffect) continue;
9031
+ const bareNestedEffectGen = yield* orUndefined(typeParser.effectGen(node.expression));
9032
+ if (!bareNestedEffectGen) continue;
9033
+ report({
9034
+ location: node.expression,
9035
+ messageText: "This `yield*` is applied to a nested `Effect.gen(...)` that can be inlined in the parent Effect generator context.",
9036
+ fixes: []
9037
+ });
9038
+ }
9039
+ })
9040
+ });
9041
+
9042
+ // src/diagnostics/newPromise.ts
9043
+ var newPromise = createDiagnostic({
9044
+ name: "newPromise",
9045
+ code: 68,
9046
+ description: "Warns when constructing promises with new Promise instead of using Effect APIs",
9047
+ group: "effectNative",
9048
+ severity: "off",
9049
+ fixable: false,
9050
+ supportedEffect: ["v3", "v4"],
9051
+ apply: fn("newPromise.apply")(function* (sourceFile, report) {
9052
+ const ts = yield* service(TypeScriptApi);
9053
+ const typeChecker = yield* service(TypeCheckerApi);
9054
+ const typeCheckerUtils = yield* service(TypeCheckerUtils);
9055
+ const promiseSymbol = typeChecker.resolveName("Promise", void 0, ts.SymbolFlags.Value, false);
9056
+ if (!promiseSymbol) return;
9057
+ const visit = (node) => {
9058
+ if (ts.isNewExpression(node)) {
9059
+ const symbol3 = typeChecker.getSymbolAtLocation(node.expression);
9060
+ if (symbol3 && typeCheckerUtils.resolveToGlobalSymbol(symbol3) === promiseSymbol) {
9061
+ report({
9062
+ location: node,
9063
+ messageText: "This code constructs `new Promise(...)`, prefer Effect APIs such as `Effect.async`, `Effect.promise`, or `Effect.tryPromise` instead of manual Promise construction.",
9064
+ fixes: []
9065
+ });
9066
+ }
9067
+ }
9068
+ ts.forEachChild(node, visit);
9069
+ return void 0;
9070
+ };
9071
+ ts.forEachChild(sourceFile, visit);
9072
+ })
9073
+ });
9074
+
8761
9075
  // src/diagnostics/nodeBuiltinImport.ts
8762
9076
  var moduleAlternativesV3 = /* @__PURE__ */ new Map([
8763
9077
  ["fs", { alternative: "FileSystem", module: "fs", package: "@effect/platform" }],
@@ -8814,7 +9128,7 @@ var nodeBuiltinImport = createDiagnostic({
8814
9128
  if (match2) {
8815
9129
  report({
8816
9130
  location: statement.moduleSpecifier,
8817
- messageText: `Prefer using ${match2.alternative} from ${match2.package} instead of the Node.js '${match2.module}' module.`,
9131
+ messageText: `This module reference uses the \`${match2.module}\` module, the corresponding Effect API is \`${match2.alternative}\` from \`${match2.package}\`.`,
8818
9132
  fixes: []
8819
9133
  });
8820
9134
  }
@@ -8827,7 +9141,7 @@ var nodeBuiltinImport = createDiagnostic({
8827
9141
  if (match2) {
8828
9142
  report({
8829
9143
  location: arg,
8830
- messageText: `Prefer using ${match2.alternative} from ${match2.package} instead of the Node.js '${match2.module}' module.`,
9144
+ messageText: `This module reference uses the \`${match2.module}\` module, the corresponding Effect API is \`${match2.alternative}\` from \`${match2.package}\`.`,
8831
9145
  fixes: []
8832
9146
  });
8833
9147
  }
@@ -8881,7 +9195,7 @@ var nonObjectEffectServiceType = createDiagnostic({
8881
9195
  const propertyValue = property.initializer;
8882
9196
  const errorToReport = {
8883
9197
  location: property.name,
8884
- 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.",
9198
+ 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.",
8885
9199
  fixes: []
8886
9200
  };
8887
9201
  if (propertyName === "succeed") {
@@ -9101,6 +9415,14 @@ var effectModuleMigrationDb = {
9101
9415
  "yieldNow": asUnchanged,
9102
9416
  "zip": asUnchanged,
9103
9417
  "zipWith": asUnchanged,
9418
+ "annotateLogsScoped": asUnchanged,
9419
+ "awaitAllChildren": asUnchanged,
9420
+ "bind": asUnchanged,
9421
+ "bindTo": asUnchanged,
9422
+ "Do": asUnchanged,
9423
+ "let": asUnchanged,
9424
+ "partition": asUnchanged,
9425
+ "validate": asUnchanged,
9104
9426
  // Renamed APIs (v3 name → v4 name)
9105
9427
  "catchAll": asRenamedSameBehaviour("catch"),
9106
9428
  "catchAllCause": asRenamedSameBehaviour("catchCause"),
@@ -9120,14 +9442,6 @@ var effectModuleMigrationDb = {
9120
9442
  "serviceOptional": asRenamedSameBehaviour("serviceOption"),
9121
9443
  "tapErrorCause": asRenamedSameBehaviour("tapCause"),
9122
9444
  // Removed APIs
9123
- "annotateLogsScoped": asUnchanged,
9124
- "awaitAllChildren": asUnchanged,
9125
- "bind": asUnchanged,
9126
- "bindTo": asUnchanged,
9127
- "Do": asUnchanged,
9128
- "let": asUnchanged,
9129
- "partition": asUnchanged,
9130
- "validate": asUnchanged,
9131
9445
  "catchSomeDefect": asRemoved(
9132
9446
  "Use Effect.catchDefect or Effect.matchCause to handle specific defects."
9133
9447
  ),
@@ -9643,7 +9957,7 @@ var outdatedApi = createDiagnostic({
9643
9957
  hasReported = true;
9644
9958
  report({
9645
9959
  location: propertyAccess.name,
9646
- messageText: `${propertyName} is an Effect v3 API, but the project is using Effect v4.`,
9960
+ 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.`,
9647
9961
  fixes: []
9648
9962
  });
9649
9963
  }
@@ -9686,7 +10000,7 @@ var outdatedApi = createDiagnostic({
9686
10000
  if (hasReported) {
9687
10001
  report({
9688
10002
  location: { pos: 0, end: 0 },
9689
- 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.",
10003
+ 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.",
9690
10004
  fixes: []
9691
10005
  });
9692
10006
  }
@@ -10931,7 +11245,7 @@ var overriddenSchemaConstructor = createDiagnostic({
10931
11245
  };
10932
11246
  report({
10933
11247
  location: member,
10934
- 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.",
11248
+ 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.",
10935
11249
  fixes: (member.body ? [fixAsStaticNew] : []).concat([{
10936
11250
  fixName: "overriddenSchemaConstructor_fix",
10937
11251
  description: "Remove the constructor override",
@@ -11053,7 +11367,7 @@ var preferSchemaOverJson = createDiagnostic({
11053
11367
  if (isSome2(match2)) {
11054
11368
  report({
11055
11369
  location: match2.value,
11056
- messageText: "Consider using Effect Schema for JSON operations instead of JSON.parse/JSON.stringify",
11370
+ messageText: "This code uses `JSON.parse` or `JSON.stringify`. Effect Schema provides Effect-aware APIs for JSON parsing and stringifying.",
11057
11371
  fixes: []
11058
11372
  });
11059
11373
  }
@@ -11061,6 +11375,63 @@ var preferSchemaOverJson = createDiagnostic({
11061
11375
  })
11062
11376
  });
11063
11377
 
11378
+ // src/diagnostics/processEnvInEffect.ts
11379
+ var isEnvPropertyAccess = (tsApi, node) => tsApi.isPropertyAccessExpression(node) && tsApi.idText(node.name) === "env";
11380
+ var isProcessEnvMemberAccess = (tsApi, node) => (tsApi.isPropertyAccessExpression(node) || tsApi.isElementAccessExpression(node)) && isEnvPropertyAccess(tsApi, node.expression);
11381
+ var makeProcessEnvApply = (checkInEffect) => fn(`processEnv${checkInEffect ? "InEffect" : ""}.apply`)(function* (sourceFile, report) {
11382
+ const ts = yield* service(TypeScriptApi);
11383
+ const typeChecker = yield* service(TypeCheckerApi);
11384
+ const typeCheckerUtils = yield* service(TypeCheckerUtils);
11385
+ const typeParser = yield* service(TypeParser);
11386
+ const processSymbol = typeChecker.resolveName("process", void 0, ts.SymbolFlags.Value, false);
11387
+ if (!processSymbol) return;
11388
+ const nodeToVisit = [];
11389
+ const appendNodeToVisit = (node) => {
11390
+ nodeToVisit.push(node);
11391
+ return void 0;
11392
+ };
11393
+ ts.forEachChild(sourceFile, appendNodeToVisit);
11394
+ while (nodeToVisit.length > 0) {
11395
+ const node = nodeToVisit.shift();
11396
+ ts.forEachChild(node, appendNodeToVisit);
11397
+ if (!isProcessEnvMemberAccess(ts, node)) continue;
11398
+ const processNode = node.expression.expression;
11399
+ if (!ts.isIdentifier(processNode) || ts.idText(processNode) !== "process") continue;
11400
+ const symbol3 = typeChecker.getSymbolAtLocation(processNode);
11401
+ if (!symbol3) continue;
11402
+ if (typeCheckerUtils.resolveToGlobalSymbol(symbol3) !== processSymbol) continue;
11403
+ const { inEffect } = yield* typeParser.findEnclosingScopes(node);
11404
+ if (inEffect !== checkInEffect) continue;
11405
+ report({
11406
+ location: node,
11407
+ 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.",
11408
+ fixes: []
11409
+ });
11410
+ }
11411
+ });
11412
+ var processEnvInEffect = createDiagnostic({
11413
+ name: "processEnvInEffect",
11414
+ code: 65,
11415
+ description: "Warns when reading process.env inside Effect generators instead of using Effect Config",
11416
+ group: "effectNative",
11417
+ severity: "off",
11418
+ fixable: false,
11419
+ supportedEffect: ["v3", "v4"],
11420
+ apply: makeProcessEnvApply(true)
11421
+ });
11422
+
11423
+ // src/diagnostics/processEnv.ts
11424
+ var processEnv = createDiagnostic({
11425
+ name: "processEnv",
11426
+ code: 64,
11427
+ description: "Warns when reading process.env outside Effect generators instead of using Effect Config",
11428
+ group: "effectNative",
11429
+ severity: "off",
11430
+ fixable: false,
11431
+ supportedEffect: ["v3", "v4"],
11432
+ apply: makeProcessEnvApply(false)
11433
+ });
11434
+
11064
11435
  // src/diagnostics/redundantSchemaTagIdentifier.ts
11065
11436
  var redundantSchemaTagIdentifier = createDiagnostic({
11066
11437
  name: "redundantSchemaTagIdentifier",
@@ -11171,9 +11542,7 @@ var returnEffectInGen = createDiagnostic({
11171
11542
  }] : [];
11172
11543
  report({
11173
11544
  location: node,
11174
- messageText: `You are returning an Effect-able type inside a generator function, and will result in nested Effect<Effect<...>>.
11175
- Maybe you wanted to return yield* instead?
11176
- 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.`,
11545
+ 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.",
11177
11546
  fixes: fix
11178
11547
  });
11179
11548
  }),
@@ -11328,9 +11697,7 @@ var runEffectInsideEffect = createDiagnostic({
11328
11697
  );
11329
11698
  });
11330
11699
  const v4MethodName = `${isEffectRunCall.value.methodName}With`;
11331
- const messageText = supportedEffect === "v4" ? `Using ${nodeText} inside an Effect is not recommended. The same services should generally be used instead to run child effects.
11332
- 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.
11333
- Consider extracting the Runtime by using for example Effect.runtime and then use Runtime.${isEffectRunCall.value.methodName} with the extracted runtime instead.`;
11700
+ 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}\`.`;
11334
11701
  report({
11335
11702
  location: node.expression,
11336
11703
  messageText,
@@ -11343,7 +11710,7 @@ Consider extracting the Runtime by using for example Effect.runtime and then use
11343
11710
  } else {
11344
11711
  report({
11345
11712
  location: node.expression,
11346
- messageText: `Using ${nodeText} inside an Effect is not recommended. Effects inside generators can usually just be yielded.`,
11713
+ messageText: `\`${nodeText}\` is called inside an existing Effect context. Here, the inner Effect can be used directly.`,
11347
11714
  fixes: []
11348
11715
  });
11349
11716
  }
@@ -11398,7 +11765,7 @@ var schemaStructWithTag = createDiagnostic({
11398
11765
  const otherProperties = arg.properties.filter((prop) => prop !== tagProperty);
11399
11766
  report({
11400
11767
  location: node,
11401
- messageText: "Schema.Struct with a _tag field can be simplified to Schema.TaggedStruct to make the tag optional in the constructor.",
11768
+ 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.",
11402
11769
  fixes: [{
11403
11770
  fixName: "schemaStructWithTag_fix",
11404
11771
  description: "Replace with Schema.TaggedStruct",
@@ -11491,7 +11858,7 @@ var schemaSyncInEffect = createDiagnostic({
11491
11858
  const effectMethodName = syncToEffectMethod[isSchemaSyncCall.value.methodName];
11492
11859
  report({
11493
11860
  location: node.expression,
11494
- messageText: `Using ${nodeText} inside an Effect generator is not recommended. Use Schema.${effectMethodName} instead to get properly typed error channel.`,
11861
+ messageText: `\`${nodeText}\` is used inside an Effect generator. \`Schema.${effectMethodName}\` preserves the typed Effect error channel for this operation without throwing.`,
11495
11862
  fixes: []
11496
11863
  });
11497
11864
  }
@@ -11551,7 +11918,7 @@ var schemaUnionOfLiterals = createDiagnostic({
11551
11918
  const schemaLiteralExpression = firstLiteralCall.expression;
11552
11919
  report({
11553
11920
  location: node,
11554
- messageText: "A Schema.Union of multiple Schema.Literal calls can be simplified to a single Schema.Literal call.",
11921
+ messageText: "This `Schema.Union` contains multiple `Schema.Literal` members and can be simplified to a single `Schema.Literal` call.",
11555
11922
  fixes: [{
11556
11923
  fixName: "schemaUnionOfLiterals_fix",
11557
11924
  description: "Replace with a single Schema.Literal call",
@@ -11614,8 +11981,7 @@ var scopeInLayerEffect = createDiagnostic({
11614
11981
  map4(
11615
11982
  () => report({
11616
11983
  location: node,
11617
- messageText: `Seems like you are constructing a layer with a scope in the requirements.
11618
- Consider using "scoped" instead to get rid of the scope in the requirements.`,
11984
+ messageText: "This layer construction leaves `Scope` in the requirement set. The scoped API removes `Scope` from the resulting requirements.",
11619
11985
  fixes: methodIdentifier ? [{
11620
11986
  fixName: "scopeInLayerEffect_scoped",
11621
11987
  description: "Use scoped for Layer creation",
@@ -11715,7 +12081,7 @@ var serviceNotAsClass = createDiagnostic({
11715
12081
  const shapeText = typeArgs.length > 0 ? typeArgs.map((t) => sourceFile.text.substring(ts.getTokenPosOfNode(t, sourceFile), t.end)).join(", ") : "Shape";
11716
12082
  report({
11717
12083
  location: callExpr,
11718
- 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, "")}") {}`,
12084
+ 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, "")}") {}\`.`,
11719
12085
  fixes: [{
11720
12086
  fixName: "serviceNotAsClass",
11721
12087
  description: `Convert to class declaration`,
@@ -11928,7 +12294,7 @@ var tryCatchInEffectGen = createDiagnostic({
11928
12294
  map4(() => {
11929
12295
  report({
11930
12296
  location: node,
11931
- messageText: `Avoid using try/catch inside Effect generators. Use Effect's error handling mechanisms instead (e.g. ${alternatives.join(", ")}).`,
12297
+ messageText: `This Effect generator contains \`try/catch\`; in this context, error handling is expressed with Effect APIs such as ${alternatives.join(", ")}).`,
11932
12298
  fixes: []
11933
12299
  });
11934
12300
  }),
@@ -11989,8 +12355,7 @@ var unknownInEffectCatch = createDiagnostic({
11989
12355
  );
11990
12356
  report({
11991
12357
  location: node.expression,
11992
- messageText: `The 'catch' callback in ${nodeText} returns 'unknown'. The catch callback should be used to provide typed errors.
11993
- Consider wrapping unknown errors into Effect's Data.TaggedError for example, or narrow down the type to the specific error raised.`,
12358
+ 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\`.`,
11994
12359
  fixes: []
11995
12360
  });
11996
12361
  }
@@ -12004,6 +12369,56 @@ Consider wrapping unknown errors into Effect's Data.TaggedError for example, or
12004
12369
  })
12005
12370
  });
12006
12371
 
12372
+ // src/diagnostics/unnecessaryArrowBlock.ts
12373
+ var unnecessaryArrowBlock = createDiagnostic({
12374
+ name: "unnecessaryArrowBlock",
12375
+ code: 72,
12376
+ description: "Suggests using a concise arrow body when the block only returns an expression",
12377
+ group: "style",
12378
+ severity: "off",
12379
+ fixable: true,
12380
+ supportedEffect: ["v3", "v4"],
12381
+ apply: fn("unnecessaryArrowBlock.apply")(function* (sourceFile, report) {
12382
+ const ts = yield* service(TypeScriptApi);
12383
+ const nodeToVisit = [];
12384
+ const appendNodeToVisit = (node) => {
12385
+ nodeToVisit.push(node);
12386
+ return void 0;
12387
+ };
12388
+ ts.forEachChild(sourceFile, appendNodeToVisit);
12389
+ while (nodeToVisit.length > 0) {
12390
+ const node = nodeToVisit.shift();
12391
+ ts.forEachChild(node, appendNodeToVisit);
12392
+ if (!ts.isArrowFunction(node) || !ts.isBlock(node.body)) continue;
12393
+ if (node.body.statements.length !== 1) continue;
12394
+ const [statement] = node.body.statements;
12395
+ if (!ts.isReturnStatement(statement) || !statement.expression) continue;
12396
+ const returnedExpression = statement.expression;
12397
+ report({
12398
+ location: node.body,
12399
+ messageText: "This arrow function block only returns an expression and can use a concise body.",
12400
+ fixes: [{
12401
+ fixName: "unnecessaryArrowBlock_fix",
12402
+ description: "Use a concise arrow body",
12403
+ apply: gen(function* () {
12404
+ const changeTracker = yield* service(ChangeTracker);
12405
+ const replacementNode = ts.factory.updateArrowFunction(
12406
+ node,
12407
+ node.modifiers,
12408
+ node.typeParameters,
12409
+ node.parameters,
12410
+ node.type,
12411
+ node.equalsGreaterThanToken,
12412
+ ts.factory.createParenthesizedExpression(returnedExpression)
12413
+ );
12414
+ changeTracker.replaceNode(sourceFile, node, replacementNode);
12415
+ })
12416
+ }]
12417
+ });
12418
+ }
12419
+ })
12420
+ });
12421
+
12007
12422
  // src/diagnostics/unnecessaryEffectGen.ts
12008
12423
  var unnecessaryEffectGen = createDiagnostic({
12009
12424
  name: "unnecessaryEffectGen",
@@ -12087,7 +12502,7 @@ var unnecessaryFailYieldableError = createDiagnostic({
12087
12502
  map4(
12088
12503
  () => report({
12089
12504
  location: node,
12090
- messageText: `This Effect.fail call uses a yieldable error type as argument. You can yield* the error directly instead.`,
12505
+ messageText: "This `yield* Effect.fail(...)` passes a yieldable error value. `yield*` represents that value directly without wrapping it in `Effect.fail`.",
12091
12506
  fixes: [{
12092
12507
  fixName: "unnecessaryFailYieldableError_fix",
12093
12508
  description: "Replace yield* Effect.fail with yield*",
@@ -12192,7 +12607,7 @@ var unnecessaryPipeChain = createDiagnostic({
12192
12607
  map4(({ innerCall, pipeCall }) => {
12193
12608
  report({
12194
12609
  location: node,
12195
- messageText: `Chained pipe calls can be simplified to a single pipe call`,
12610
+ messageText: "This expression contains chained `pipe` calls that can be simplified to a single `pipe` call.",
12196
12611
  fixes: [{
12197
12612
  fixName: "unnecessaryPipeChain_fix",
12198
12613
  description: "Rewrite as single pipe call",
@@ -12304,12 +12719,17 @@ var unsupportedServiceAccessors = createDiagnostic({
12304
12719
  var diagnostics = [
12305
12720
  outdatedApi,
12306
12721
  anyUnknownInErrorContext,
12722
+ asyncFunction,
12307
12723
  instanceOfSchema,
12308
12724
  catchAllToMapError,
12309
12725
  catchUnfailableEffect,
12310
12726
  classSelfMismatch,
12727
+ cryptoRandomUUID,
12728
+ cryptoRandomUUIDInEffect,
12311
12729
  duplicatePackage,
12730
+ effectDoNotation,
12312
12731
  effectFnImplicitAny,
12732
+ effectMapFlatten,
12313
12733
  effectGenUsesAdapter,
12314
12734
  missingEffectContext,
12315
12735
  missingEffectError,
@@ -12318,6 +12738,8 @@ var diagnostics = [
12318
12738
  floatingEffect,
12319
12739
  effectInFailure,
12320
12740
  missingStarInYieldEffectGen,
12741
+ newPromise,
12742
+ lazyPromiseInEffectSync,
12321
12743
  unnecessaryEffectGen,
12322
12744
  unnecessaryFailYieldableError,
12323
12745
  missingReturnYieldStar,
@@ -12326,6 +12748,8 @@ var diagnostics = [
12326
12748
  genericEffectServices,
12327
12749
  globalFetch,
12328
12750
  globalFetchInEffect,
12751
+ processEnv,
12752
+ processEnvInEffect,
12329
12753
  returnEffectInGen,
12330
12754
  tryCatchInEffectGen,
12331
12755
  importFromBarrel,
@@ -12343,6 +12767,8 @@ var diagnostics = [
12343
12767
  strictEffectProvide,
12344
12768
  unknownInEffectCatch,
12345
12769
  runEffectInsideEffect,
12770
+ nestedEffectGenYield,
12771
+ unnecessaryArrowBlock,
12346
12772
  schemaUnionOfLiterals,
12347
12773
  schemaStructWithTag,
12348
12774
  globalErrorInEffectCatch,