@effect/language-service 0.64.1 → 0.66.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Function.js
3
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/Function.js
4
4
  var isFunction = (input) => typeof input === "function";
5
5
  var dual = function(arity, body) {
6
6
  if (typeof arity === "function") {
@@ -98,7 +98,7 @@ function pipe(a, ab, bc, cd, de, ef, fg, gh, hi) {
98
98
  }
99
99
  }
100
100
 
101
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Equivalence.js
101
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/Equivalence.js
102
102
  var make = (isEquivalent) => (self, that) => self === that || isEquivalent(self, that);
103
103
  var array = (item) => make((self, that) => {
104
104
  if (self.length !== that.length) {
@@ -113,7 +113,7 @@ var array = (item) => make((self, that) => {
113
113
  return true;
114
114
  });
115
115
 
116
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/GlobalValue.js
116
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/GlobalValue.js
117
117
  var globalStoreId = `effect/GlobalValue`;
118
118
  var globalStore;
119
119
  var globalValue = (id, compute) => {
@@ -127,7 +127,7 @@ var globalValue = (id, compute) => {
127
127
  return globalStore.get(id);
128
128
  };
129
129
 
130
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Predicate.js
130
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/Predicate.js
131
131
  var isString = (input) => typeof input === "string";
132
132
  var isNumber = (input) => typeof input === "number";
133
133
  var isBoolean = (input) => typeof input === "boolean";
@@ -138,10 +138,10 @@ var hasProperty = /* @__PURE__ */ dual(2, (self, property) => isObject(self) &&
138
138
  var isTagged = /* @__PURE__ */ dual(2, (self, tag) => hasProperty(self, "_tag") && self["_tag"] === tag);
139
139
  var isRecord = (input) => isRecordOrArray(input) && !Array.isArray(input);
140
140
 
141
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/errors.js
141
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/internal/errors.js
142
142
  var getBugErrorMessage = (message) => `BUG: ${message} - please report an issue at https://github.com/Effect-TS/effect/issues`;
143
143
 
144
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Utils.js
144
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/Utils.js
145
145
  var GenKindTypeId = /* @__PURE__ */ Symbol.for("effect/Gen/GenKind");
146
146
  var GenKindImpl = class {
147
147
  value;
@@ -263,7 +263,7 @@ var internalCall = isNotOptimizedAway ? standard.effect_internal_function : forc
263
263
  var genConstructor = function* () {
264
264
  }.constructor;
265
265
 
266
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Hash.js
266
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/Hash.js
267
267
  var randomHashCache = /* @__PURE__ */ globalValue(/* @__PURE__ */ Symbol.for("effect/Hash/randomHashCache"), () => /* @__PURE__ */ new WeakMap());
268
268
  var symbol = /* @__PURE__ */ Symbol.for("effect/Hash");
269
269
  var hash = (self) => {
@@ -372,7 +372,7 @@ var cached = function() {
372
372
  return hash2;
373
373
  };
374
374
 
375
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Equal.js
375
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/Equal.js
376
376
  var symbol2 = /* @__PURE__ */ Symbol.for("effect/Equal");
377
377
  function equals() {
378
378
  if (arguments.length === 1) {
@@ -428,7 +428,7 @@ function compareBoth(self, that) {
428
428
  var isEqual = (u) => hasProperty(u, symbol2);
429
429
  var equivalence = () => equals;
430
430
 
431
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Inspectable.js
431
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/Inspectable.js
432
432
  var NodeInspectSymbol = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
433
433
  var toJSON = (x) => {
434
434
  try {
@@ -486,7 +486,7 @@ var redact = (u) => {
486
486
  return u;
487
487
  };
488
488
 
489
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Pipeable.js
489
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/Pipeable.js
490
490
  var pipeArguments = (self, args2) => {
491
491
  switch (args2.length) {
492
492
  case 0:
@@ -519,16 +519,16 @@ var pipeArguments = (self, args2) => {
519
519
  }
520
520
  };
521
521
 
522
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/opCodes/effect.js
522
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/internal/opCodes/effect.js
523
523
  var OP_COMMIT = "Commit";
524
524
  var OP_FAILURE = "Failure";
525
525
  var OP_WITH_RUNTIME = "WithRuntime";
526
526
 
527
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/version.js
528
- var moduleVersion = "3.19.13";
527
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/internal/version.js
528
+ var moduleVersion = "3.19.14";
529
529
  var getCurrentVersion = () => moduleVersion;
530
530
 
531
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/effectable.js
531
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/internal/effectable.js
532
532
  var EffectTypeId = /* @__PURE__ */ Symbol.for("effect/Effect");
533
533
  var StreamTypeId = /* @__PURE__ */ Symbol.for("effect/Stream");
534
534
  var SinkTypeId = /* @__PURE__ */ Symbol.for("effect/Sink");
@@ -615,7 +615,7 @@ var StructuralCommitPrototype = {
615
615
  ...StructuralPrototype
616
616
  };
617
617
 
618
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/option.js
618
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/internal/option.js
619
619
  var TypeId = /* @__PURE__ */ Symbol.for("effect/Option");
620
620
  var CommonProto = {
621
621
  ...EffectPrototype,
@@ -673,7 +673,7 @@ var some = (value) => {
673
673
  return a;
674
674
  };
675
675
 
676
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/either.js
676
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/internal/either.js
677
677
  var TypeId2 = /* @__PURE__ */ Symbol.for("effect/Either");
678
678
  var CommonProto2 = {
679
679
  ...EffectPrototype,
@@ -735,7 +735,7 @@ var right = (right3) => {
735
735
  return a;
736
736
  };
737
737
 
738
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Either.js
738
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/Either.js
739
739
  var right2 = right;
740
740
  var left2 = left;
741
741
  var isLeft2 = isLeft;
@@ -743,10 +743,10 @@ var isRight2 = isRight;
743
743
  var map = /* @__PURE__ */ dual(2, (self, f) => isRight2(self) ? right2(f(self.right)) : left2(self.left));
744
744
  var getOrElse = /* @__PURE__ */ dual(2, (self, onLeft) => isLeft2(self) ? onLeft(self.left) : self.right);
745
745
 
746
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/array.js
746
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/internal/array.js
747
747
  var isNonEmptyArray = (self) => self.length > 0;
748
748
 
749
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Order.js
749
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/Order.js
750
750
  var make2 = (compare) => (self, that) => self === that ? 0 : compare(self, that);
751
751
  var string2 = /* @__PURE__ */ make2((self, that) => self < that ? -1 : 1);
752
752
  var number2 = /* @__PURE__ */ make2((self, that) => self < that ? -1 : 1);
@@ -760,7 +760,7 @@ var combine2 = /* @__PURE__ */ dual(2, (self, that) => make2((a1, a2) => {
760
760
  }));
761
761
  var mapInput = /* @__PURE__ */ dual(2, (self, f) => make2((b1, b2) => self(f(b1), f(b2))));
762
762
 
763
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Option.js
763
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/Option.js
764
764
  var none2 = () => none;
765
765
  var some2 = some;
766
766
  var isNone2 = isNone;
@@ -771,7 +771,7 @@ var fromNullable = (nullableValue) => nullableValue == null ? none2() : some2(nu
771
771
  var getOrUndefined = /* @__PURE__ */ getOrElse2(constUndefined);
772
772
  var map2 = /* @__PURE__ */ dual(2, (self, f) => isNone2(self) ? none2() : some2(f(self.value)));
773
773
 
774
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Record.js
774
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/Record.js
775
775
  var map3 = /* @__PURE__ */ dual(2, (self, f) => {
776
776
  const out = {
777
777
  ...self
@@ -783,7 +783,7 @@ var map3 = /* @__PURE__ */ dual(2, (self, f) => {
783
783
  });
784
784
  var keys = (self) => Object.keys(self);
785
785
 
786
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Array.js
786
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/Array.js
787
787
  var fromIterable = (collection) => Array.isArray(collection) ? collection : Array.from(collection);
788
788
  var append = /* @__PURE__ */ dual(2, (self, last) => [...self, last]);
789
789
  var appendAll = /* @__PURE__ */ dual(2, (self, that) => fromIterable(self).concat(fromIterable(that)));
@@ -887,7 +887,7 @@ var dedupeWith = /* @__PURE__ */ dual(2, (self, isEquivalent) => {
887
887
  var dedupe = (self) => dedupeWith(self, equivalence());
888
888
  var join = /* @__PURE__ */ dual(2, (self, sep) => fromIterable(self).join(sep));
889
889
 
890
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Chunk.js
890
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/Chunk.js
891
891
  var TypeId3 = /* @__PURE__ */ Symbol.for("effect/Chunk");
892
892
  function copy(src, srcPos, dest, destPos, len) {
893
893
  for (let i = srcPos; i < Math.min(src.length, srcPos + len); i++) {
@@ -1183,14 +1183,14 @@ var isNonEmpty = (self) => self.length > 0;
1183
1183
  var unsafeHead = (self) => unsafeGet2(self, 0);
1184
1184
  var headNonEmpty2 = unsafeHead;
1185
1185
 
1186
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/hashMap/config.js
1186
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/internal/hashMap/config.js
1187
1187
  var SIZE = 5;
1188
1188
  var BUCKET_SIZE = /* @__PURE__ */ Math.pow(2, SIZE);
1189
1189
  var MASK = BUCKET_SIZE - 1;
1190
1190
  var MAX_INDEX_NODE = BUCKET_SIZE / 2;
1191
1191
  var MIN_ARRAY_NODE = BUCKET_SIZE / 4;
1192
1192
 
1193
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/hashMap/bitwise.js
1193
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/internal/hashMap/bitwise.js
1194
1194
  function popcount(x) {
1195
1195
  x -= x >> 1 & 1431655765;
1196
1196
  x = (x & 858993459) + (x >> 2 & 858993459);
@@ -1209,13 +1209,13 @@ function fromBitmap(bitmap, bit) {
1209
1209
  return popcount(bitmap & bit - 1);
1210
1210
  }
1211
1211
 
1212
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/stack.js
1212
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/internal/stack.js
1213
1213
  var make4 = (value, previous) => ({
1214
1214
  value,
1215
1215
  previous
1216
1216
  });
1217
1217
 
1218
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/hashMap/array.js
1218
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/internal/hashMap/array.js
1219
1219
  function arrayUpdate(mutate3, at, v, arr) {
1220
1220
  let out = arr;
1221
1221
  if (!mutate3) {
@@ -1260,7 +1260,7 @@ function arraySpliceIn(mutate3, at, v, arr) {
1260
1260
  return out;
1261
1261
  }
1262
1262
 
1263
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/hashMap/node.js
1263
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/internal/hashMap/node.js
1264
1264
  var EmptyNode = class _EmptyNode {
1265
1265
  _tag = "EmptyNode";
1266
1266
  modify(edit, _shift, f, hash2, key, size4) {
@@ -1495,7 +1495,7 @@ function mergeLeaves(edit, shift, h1, n1, h2, n2) {
1495
1495
  }
1496
1496
  }
1497
1497
 
1498
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/hashMap.js
1498
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/internal/hashMap.js
1499
1499
  var HashMapSymbolKey = "effect/HashMap";
1500
1500
  var HashMapTypeId = /* @__PURE__ */ Symbol.for(HashMapSymbolKey);
1501
1501
  var HashMapProto = {
@@ -1707,7 +1707,7 @@ var reduce2 = /* @__PURE__ */ dual(3, (self, zero2, f) => {
1707
1707
  return zero2;
1708
1708
  });
1709
1709
 
1710
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/hashSet.js
1710
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/internal/hashSet.js
1711
1711
  var HashSetSymbolKey = "effect/HashSet";
1712
1712
  var HashSetTypeId = /* @__PURE__ */ Symbol.for(HashSetSymbolKey);
1713
1713
  var HashSetProto = {
@@ -1769,13 +1769,13 @@ var union2 = /* @__PURE__ */ dual(2, (self, that) => mutate(empty4(), (set2) =>
1769
1769
  }));
1770
1770
  var forEach2 = /* @__PURE__ */ dual(2, (self, f) => forEach(self._keyMap, (_, k) => f(k)));
1771
1771
 
1772
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/HashSet.js
1772
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/HashSet.js
1773
1773
  var empty5 = empty4;
1774
1774
  var size3 = size2;
1775
1775
  var add2 = add;
1776
1776
  var union3 = union2;
1777
1777
 
1778
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/data.js
1778
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/internal/data.js
1779
1779
  var ArrayProto = /* @__PURE__ */ Object.assign(/* @__PURE__ */ Object.create(Array.prototype), {
1780
1780
  [symbol]() {
1781
1781
  return cached(this, array2(this));
@@ -1798,7 +1798,7 @@ var Structural = /* @__PURE__ */ (function() {
1798
1798
  return Structural2;
1799
1799
  })();
1800
1800
 
1801
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/opCodes/cause.js
1801
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/internal/opCodes/cause.js
1802
1802
  var OP_DIE = "Die";
1803
1803
  var OP_EMPTY = "Empty";
1804
1804
  var OP_FAIL = "Fail";
@@ -1806,7 +1806,7 @@ var OP_INTERRUPT = "Interrupt";
1806
1806
  var OP_PARALLEL = "Parallel";
1807
1807
  var OP_SEQUENTIAL = "Sequential";
1808
1808
 
1809
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/cause.js
1809
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/internal/cause.js
1810
1810
  var CauseSymbolKey = "effect/Cause";
1811
1811
  var CauseTypeId = /* @__PURE__ */ Symbol.for(CauseSymbolKey);
1812
1812
  var variance = {
@@ -2238,7 +2238,7 @@ var prettyErrors = (cause) => reduceWithContext(cause, void 0, {
2238
2238
  sequentialCase: (_, l, r) => [...l, ...r]
2239
2239
  });
2240
2240
 
2241
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/singleShotGen.js
2241
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/internal/singleShotGen.js
2242
2242
  var SingleShotGen2 = class _SingleShotGen {
2243
2243
  self;
2244
2244
  called = false;
@@ -2268,7 +2268,7 @@ var SingleShotGen2 = class _SingleShotGen {
2268
2268
  }
2269
2269
  };
2270
2270
 
2271
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/core.js
2271
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/internal/core.js
2272
2272
  var EffectTypeId2 = /* @__PURE__ */ Symbol.for("effect/Effect");
2273
2273
  var EffectPrimitive = class {
2274
2274
  _op;
@@ -2552,7 +2552,7 @@ var currentSpanFromFiber = (fiber) => {
2552
2552
  return span !== void 0 && span._tag === "Span" ? some2(span) : none2();
2553
2553
  };
2554
2554
 
2555
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Data.js
2555
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/Data.js
2556
2556
  var Class2 = Structural;
2557
2557
  var Error2 = /* @__PURE__ */ (function() {
2558
2558
  const plainArgsSymbol = /* @__PURE__ */ Symbol.for("effect/Data/Error/plainArgs");
@@ -2590,10 +2590,10 @@ var TaggedError = (tag) => {
2590
2590
  return O.BaseEffectError;
2591
2591
  };
2592
2592
 
2593
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/encoding/common.js
2593
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/internal/encoding/common.js
2594
2594
  var encoder = /* @__PURE__ */ new TextEncoder();
2595
2595
 
2596
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/encoding/base64.js
2596
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/internal/encoding/base64.js
2597
2597
  var encode = (bytes) => {
2598
2598
  const length = bytes.length;
2599
2599
  let result = "";
@@ -2619,13 +2619,13 @@ var encode = (bytes) => {
2619
2619
  };
2620
2620
  var base64abc = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "/"];
2621
2621
 
2622
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/encoding/base64Url.js
2622
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/internal/encoding/base64Url.js
2623
2623
  var encode2 = (data) => encode(data).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
2624
2624
 
2625
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Encoding.js
2625
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/Encoding.js
2626
2626
  var encodeBase64Url = (input) => typeof input === "string" ? encode2(encoder.encode(input)) : encode2(input);
2627
2627
 
2628
- // node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Graph.js
2628
+ // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/Graph.js
2629
2629
  var TypeId4 = "~effect/Graph";
2630
2630
  var Edge = class extends Class2 {
2631
2631
  };
@@ -3454,7 +3454,7 @@ var defaults = {
3454
3454
  diagnosticSeverity: {},
3455
3455
  diagnosticsName: true,
3456
3456
  missingDiagnosticNextLine: "warning",
3457
- reportSuggestionsAsWarningsInTsc: false,
3457
+ includeSuggestionsInTsc: true,
3458
3458
  quickinfo: true,
3459
3459
  quickinfoEffectParameters: "whentruncated",
3460
3460
  quickinfoMaximumLength: -1,
@@ -3478,7 +3478,7 @@ var defaults = {
3478
3478
  skipLeadingPath: ["src/"]
3479
3479
  }],
3480
3480
  extendedKeyDetection: false,
3481
- pipeableMinArgCount: 1,
3481
+ pipeableMinArgCount: 2,
3482
3482
  layerGraphFollowDepth: 0,
3483
3483
  mermaidProvider: "mermaid.live"
3484
3484
  };
@@ -3501,7 +3501,7 @@ function parse(config) {
3501
3501
  diagnosticSeverity: isObject(config) && hasProperty(config, "diagnosticSeverity") && isRecord(config.diagnosticSeverity) ? parseDiagnosticSeverity(config.diagnosticSeverity) : defaults.diagnosticSeverity,
3502
3502
  diagnosticsName: isObject(config) && hasProperty(config, "diagnosticsName") && isBoolean(config.diagnosticsName) ? config.diagnosticsName : defaults.diagnosticsName,
3503
3503
  missingDiagnosticNextLine: isObject(config) && hasProperty(config, "missingDiagnosticNextLine") && isString(config.missingDiagnosticNextLine) && isValidSeverityLevel(config.missingDiagnosticNextLine) ? config.missingDiagnosticNextLine : defaults.missingDiagnosticNextLine,
3504
- reportSuggestionsAsWarningsInTsc: isObject(config) && hasProperty(config, "reportSuggestionsAsWarningsInTsc") && isBoolean(config.reportSuggestionsAsWarningsInTsc) ? config.reportSuggestionsAsWarningsInTsc : defaults.reportSuggestionsAsWarningsInTsc,
3504
+ includeSuggestionsInTsc: isObject(config) && hasProperty(config, "includeSuggestionsInTsc") && isBoolean(config.includeSuggestionsInTsc) ? config.includeSuggestionsInTsc : defaults.includeSuggestionsInTsc,
3505
3505
  quickinfo: isObject(config) && hasProperty(config, "quickinfo") && isBoolean(config.quickinfo) ? config.quickinfo : defaults.quickinfo,
3506
3506
  quickinfoEffectParameters: isObject(config) && hasProperty(config, "quickinfoEffectParameters") && isString(config.quickinfoEffectParameters) && ["always", "never", "whentruncated"].includes(config.quickinfoEffectParameters.toLowerCase()) ? config.quickinfoEffectParameters.toLowerCase() : defaults.quickinfoEffectParameters,
3507
3507
  quickinfoMaximumLength: isObject(config) && hasProperty(config, "quickinfoMaximumLength") && isNumber(config.quickinfoMaximumLength) ? config.quickinfoMaximumLength : defaults.quickinfoMaximumLength,
@@ -4083,6 +4083,16 @@ function makeTypeScriptUtils(ts) {
4083
4083
  function isDeclarationKind(kind) {
4084
4084
  return kind === ts.SyntaxKind.ArrowFunction || kind === ts.SyntaxKind.BindingElement || kind === ts.SyntaxKind.ClassDeclaration || kind === ts.SyntaxKind.ClassExpression || kind === ts.SyntaxKind.ClassStaticBlockDeclaration || kind === ts.SyntaxKind.Constructor || kind === ts.SyntaxKind.EnumDeclaration || kind === ts.SyntaxKind.EnumMember || kind === ts.SyntaxKind.ExportSpecifier || kind === ts.SyntaxKind.FunctionDeclaration || kind === ts.SyntaxKind.FunctionExpression || kind === ts.SyntaxKind.GetAccessor || kind === ts.SyntaxKind.ImportClause || kind === ts.SyntaxKind.ImportEqualsDeclaration || kind === ts.SyntaxKind.ImportSpecifier || kind === ts.SyntaxKind.InterfaceDeclaration || kind === ts.SyntaxKind.JsxAttribute || kind === ts.SyntaxKind.MethodDeclaration || kind === ts.SyntaxKind.MethodSignature || kind === ts.SyntaxKind.ModuleDeclaration || kind === ts.SyntaxKind.NamespaceExportDeclaration || kind === ts.SyntaxKind.NamespaceImport || kind === ts.SyntaxKind.NamespaceExport || kind === ts.SyntaxKind.Parameter || kind === ts.SyntaxKind.PropertyAssignment || kind === ts.SyntaxKind.PropertyDeclaration || kind === ts.SyntaxKind.PropertySignature || kind === ts.SyntaxKind.SetAccessor || kind === ts.SyntaxKind.ShorthandPropertyAssignment || kind === ts.SyntaxKind.TypeAliasDeclaration || kind === ts.SyntaxKind.TypeParameter || kind === ts.SyntaxKind.VariableDeclaration || kind === ts.SyntaxKind.JSDocTypedefTag || kind === ts.SyntaxKind.JSDocCallbackTag || kind === ts.SyntaxKind.JSDocPropertyTag || kind === ts.SyntaxKind.NamedTupleMember;
4085
4085
  }
4086
+ function isVoidExpression(node) {
4087
+ const unwrapped = ts.isExpression(node) ? skipOuterExpressions(node) : node;
4088
+ if (ts.isVoidExpression(unwrapped) && ts.isNumericLiteral(unwrapped.expression) && unwrapped.expression.text === "0") {
4089
+ return true;
4090
+ }
4091
+ if (ts.isIdentifier(unwrapped) && ts.idText(unwrapped) === "undefined") {
4092
+ return true;
4093
+ }
4094
+ return false;
4095
+ }
4086
4096
  return {
4087
4097
  findNodeAtPositionIncludingTrivia,
4088
4098
  parsePackageContentNameAndVersionFromScope,
@@ -4106,7 +4116,8 @@ function makeTypeScriptUtils(ts) {
4106
4116
  getSourceFileOfNode,
4107
4117
  isOuterExpression,
4108
4118
  skipOuterExpressions,
4109
- isDeclarationKind
4119
+ isDeclarationKind,
4120
+ isVoidExpression
4110
4121
  };
4111
4122
  }
4112
4123
 
@@ -5364,13 +5375,15 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
5364
5375
  );
5365
5376
  }
5366
5377
  const propertyAccess = node.expression;
5378
+ const pipeArguments2 = node.arguments.slice(1);
5367
5379
  return pipe(
5368
5380
  isNodeReferenceToEffectModuleApi("fnUntraced")(propertyAccess),
5369
5381
  map8(() => ({
5370
5382
  node,
5371
5383
  effectModule: propertyAccess.expression,
5372
5384
  generatorFunction,
5373
- body: generatorFunction.body
5385
+ body: generatorFunction.body,
5386
+ pipeArguments: pipeArguments2
5374
5387
  }))
5375
5388
  );
5376
5389
  },
@@ -5409,19 +5422,112 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
5409
5422
  );
5410
5423
  }
5411
5424
  const propertyAccess = expressionToTest;
5425
+ const pipeArguments2 = node.arguments.slice(1);
5412
5426
  return pipe(
5413
5427
  isNodeReferenceToEffectModuleApi("fn")(propertyAccess),
5414
5428
  map8(() => ({
5415
5429
  node,
5416
5430
  generatorFunction,
5417
5431
  effectModule: propertyAccess.expression,
5418
- body: generatorFunction.body
5432
+ body: generatorFunction.body,
5433
+ pipeArguments: pipeArguments2
5419
5434
  }))
5420
5435
  );
5421
5436
  },
5422
5437
  "TypeParser.effectFnGen",
5423
5438
  (node) => node
5424
5439
  );
5440
+ const findEnclosingScopes = fn("TypeParser.findEnclosingScopes")(function* (startNode) {
5441
+ let currentParent = startNode.parent;
5442
+ let scopeNode = void 0;
5443
+ let effectGenResult = void 0;
5444
+ while (currentParent) {
5445
+ const nodeToCheck = currentParent;
5446
+ if (!scopeNode) {
5447
+ if (ts.isFunctionExpression(nodeToCheck) || ts.isFunctionDeclaration(nodeToCheck) || ts.isMethodDeclaration(nodeToCheck) || ts.isArrowFunction(nodeToCheck) || ts.isGetAccessorDeclaration(nodeToCheck) || ts.isSetAccessorDeclaration(nodeToCheck)) {
5448
+ scopeNode = nodeToCheck;
5449
+ }
5450
+ }
5451
+ if (!effectGenResult) {
5452
+ const isEffectGen = yield* pipe(
5453
+ effectGen(nodeToCheck),
5454
+ map8((result) => ({
5455
+ node: result.node,
5456
+ effectModule: result.effectModule,
5457
+ generatorFunction: result.generatorFunction,
5458
+ body: result.body
5459
+ })),
5460
+ orElse2(
5461
+ () => pipe(
5462
+ effectFnUntracedGen(nodeToCheck),
5463
+ map8((result) => ({
5464
+ node: result.node,
5465
+ effectModule: result.effectModule,
5466
+ generatorFunction: result.generatorFunction,
5467
+ body: result.body,
5468
+ pipeArguments: result.pipeArguments
5469
+ }))
5470
+ )
5471
+ ),
5472
+ orElse2(
5473
+ () => pipe(
5474
+ effectFnGen(nodeToCheck),
5475
+ map8((result) => ({
5476
+ node: result.node,
5477
+ effectModule: result.effectModule,
5478
+ generatorFunction: result.generatorFunction,
5479
+ body: result.body,
5480
+ pipeArguments: result.pipeArguments
5481
+ }))
5482
+ )
5483
+ ),
5484
+ option
5485
+ );
5486
+ if (isSome2(isEffectGen)) {
5487
+ effectGenResult = isEffectGen.value;
5488
+ }
5489
+ }
5490
+ if (scopeNode && effectGenResult) {
5491
+ break;
5492
+ }
5493
+ currentParent = nodeToCheck.parent;
5494
+ }
5495
+ return { scopeNode, effectGen: effectGenResult };
5496
+ });
5497
+ const effectFn = cachedBy(
5498
+ function(node) {
5499
+ if (!ts.isCallExpression(node)) {
5500
+ return typeParserIssue("Node is not a call expression", void 0, node);
5501
+ }
5502
+ if (node.arguments.length === 0) {
5503
+ return typeParserIssue("Node has no arguments", void 0, node);
5504
+ }
5505
+ const regularFunction = node.arguments[0];
5506
+ if (!ts.isFunctionExpression(regularFunction) && !ts.isArrowFunction(regularFunction)) {
5507
+ return typeParserIssue("Node is not a function expression or arrow function", void 0, node);
5508
+ }
5509
+ if (ts.isFunctionExpression(regularFunction) && regularFunction.asteriskToken !== void 0) {
5510
+ return typeParserIssue("Node is a generator function, not a regular function", void 0, node);
5511
+ }
5512
+ const expressionToTest = ts.isCallExpression(node.expression) ? node.expression.expression : node.expression;
5513
+ if (!ts.isPropertyAccessExpression(expressionToTest)) {
5514
+ return typeParserIssue("Node is not a property access expression", void 0, node);
5515
+ }
5516
+ const propertyAccess = expressionToTest;
5517
+ const pipeArguments2 = node.arguments.slice(1);
5518
+ return pipe(
5519
+ isNodeReferenceToEffectModuleApi("fn")(propertyAccess),
5520
+ map8(() => ({
5521
+ node,
5522
+ effectModule: propertyAccess.expression,
5523
+ regularFunction,
5524
+ pipeArguments: pipeArguments2
5525
+ }))
5526
+ );
5527
+ },
5528
+ "TypeParser.effectFn",
5529
+ (node) => node
5530
+ );
5425
5531
  const unnecessaryEffectGen2 = cachedBy(
5426
5532
  fn("TypeParser.unnecessaryEffectGen")(function* (node) {
5427
5533
  const { body } = yield* effectGen(node);
@@ -5533,6 +5639,28 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
5533
5639
  `TypeParser.isNodeReferenceToEffectSchemaModuleApi(${memberName})`,
5534
5640
  (node) => node
5535
5641
  );
5642
+ const isEffectParseResultSourceFile = cachedBy(
5643
+ fn("TypeParser.isEffectParseResultSourceFile")(function* (sourceFile) {
5644
+ const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
5645
+ if (!moduleSymbol) return yield* typeParserIssue("Node has no symbol", void 0, sourceFile);
5646
+ const parseIssueSymbol = typeChecker.tryGetMemberInModuleExports("ParseIssue", moduleSymbol);
5647
+ if (!parseIssueSymbol) return yield* typeParserIssue("ParseIssue type not found", void 0, sourceFile);
5648
+ const decodeSyncSymbol = typeChecker.tryGetMemberInModuleExports("decodeSync", moduleSymbol);
5649
+ if (!decodeSyncSymbol) return yield* typeParserIssue("decodeSync not found", void 0, sourceFile);
5650
+ const encodeSyncSymbol = typeChecker.tryGetMemberInModuleExports("encodeSync", moduleSymbol);
5651
+ if (!encodeSyncSymbol) return yield* typeParserIssue("encodeSync not found", void 0, sourceFile);
5652
+ return sourceFile;
5653
+ }),
5654
+ "TypeParser.isEffectParseResultSourceFile",
5655
+ (sourceFile) => sourceFile
5656
+ );
5657
+ const isNodeReferenceToEffectParseResultModuleApi = (memberName) => cachedBy(
5658
+ fn("TypeParser.isNodeReferenceToEffectParseResultModuleApi")(function* (node) {
5659
+ return yield* isNodeReferenceToExportOfPackageModule(node, "effect", isEffectParseResultSourceFile, memberName);
5660
+ }),
5661
+ `TypeParser.isNodeReferenceToEffectParseResultModuleApi(${memberName})`,
5662
+ (node) => node
5663
+ );
5536
5664
  const contextTagVarianceStruct = (type, atLocation) => map8(
5537
5665
  all(
5538
5666
  varianceStructInvariantType(type, atLocation, "_Identifier"),
@@ -5602,6 +5730,23 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
5602
5730
  "TypeParser.pipeCall",
5603
5731
  (node) => node
5604
5732
  );
5733
+ const singleArgCall = cachedBy(
5734
+ function(node) {
5735
+ if (!ts.isCallExpression(node)) {
5736
+ return typeParserIssue("Node is not a call expression", void 0, node);
5737
+ }
5738
+ if (node.arguments.length !== 1) {
5739
+ return typeParserIssue("Node must have exactly one argument", void 0, node);
5740
+ }
5741
+ return succeed({
5742
+ node,
5743
+ callee: node.expression,
5744
+ subject: node.arguments[0]
5745
+ });
5746
+ },
5747
+ "TypeParser.singleArgCall",
5748
+ (node) => node
5749
+ );
5605
5750
  const scopeType = cachedBy(
5606
5751
  fn("TypeParser.scopeType")(function* (type, atLocation) {
5607
5752
  yield* pipeableType(type, atLocation);
@@ -6140,9 +6285,333 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
6140
6285
  `TypeParser.isNodeReferenceToEffectLayerModuleApi(${memberName})`,
6141
6286
  (node) => node
6142
6287
  );
6288
+ const lazyExpression = cachedBy(
6289
+ function(node) {
6290
+ if (!ts.isArrowFunction(node) && !ts.isFunctionExpression(node)) {
6291
+ return typeParserIssue("Node is not an arrow function or function expression", void 0, node);
6292
+ }
6293
+ if (node.parameters.length !== 0) {
6294
+ return typeParserIssue("Function must have zero parameters", void 0, node);
6295
+ }
6296
+ if (node.typeParameters && node.typeParameters.length > 0) {
6297
+ return typeParserIssue("Function must have no type parameters", void 0, node);
6298
+ }
6299
+ const body = node.body;
6300
+ const returnType = node.type;
6301
+ if (ts.isArrowFunction(node) && !ts.isBlock(body)) {
6302
+ return succeed({
6303
+ node,
6304
+ body,
6305
+ expression: body,
6306
+ returnType
6307
+ });
6308
+ }
6309
+ if (ts.isBlock(body)) {
6310
+ if (body.statements.length !== 1) {
6311
+ return typeParserIssue("Block must have exactly one statement", void 0, node);
6312
+ }
6313
+ const stmt = body.statements[0];
6314
+ if (!ts.isReturnStatement(stmt)) {
6315
+ return typeParserIssue("Statement must be a return statement", void 0, node);
6316
+ }
6317
+ if (!stmt.expression) {
6318
+ return typeParserIssue("Return statement must have an expression", void 0, node);
6319
+ }
6320
+ return succeed({
6321
+ node,
6322
+ body,
6323
+ expression: stmt.expression,
6324
+ returnType
6325
+ });
6326
+ }
6327
+ return typeParserIssue("Invalid function body", void 0, node);
6328
+ },
6329
+ "TypeParser.lazyExpression",
6330
+ (node) => node
6331
+ );
6332
+ const emptyFunction = cachedBy(
6333
+ function(node) {
6334
+ if (!ts.isArrowFunction(node) && !ts.isFunctionExpression(node)) {
6335
+ return typeParserIssue("Node is not an arrow function or function expression", void 0, node);
6336
+ }
6337
+ const body = node.body;
6338
+ const returnType = node.type;
6339
+ if (!ts.isBlock(body)) {
6340
+ return typeParserIssue("Body must be a block", void 0, node);
6341
+ }
6342
+ if (body.statements.length !== 0) {
6343
+ return typeParserIssue("Block must have zero statements", void 0, node);
6344
+ }
6345
+ return succeed({
6346
+ node,
6347
+ body,
6348
+ returnType
6349
+ });
6350
+ },
6351
+ "TypeParser.emptyFunction",
6352
+ (node) => node
6353
+ );
6354
+ const pipingFlows = (includeEffectFn) => cachedBy(
6355
+ fn("TypeParser.pipingFlows")(function* (sourceFile) {
6356
+ const result = [];
6357
+ const workQueue = [[sourceFile, void 0]];
6358
+ while (workQueue.length > 0) {
6359
+ const [node, parentFlow] = workQueue.pop();
6360
+ if (ts.isCallExpression(node)) {
6361
+ const parsed = yield* pipe(
6362
+ pipeCall(node),
6363
+ map8((p) => ({ _tag: "pipe", ...p })),
6364
+ orElse2(
6365
+ () => pipe(
6366
+ singleArgCall(node),
6367
+ map8((s) => ({ _tag: "call", ...s }))
6368
+ )
6369
+ ),
6370
+ option
6371
+ );
6372
+ if (isSome2(parsed)) {
6373
+ const result2 = parsed.value;
6374
+ let transformations;
6375
+ let flowNode;
6376
+ let childrenToTraverse = [];
6377
+ if (result2._tag === "pipe") {
6378
+ const signature = typeChecker.getResolvedSignature(result2.node);
6379
+ const typeArguments = signature ? typeChecker.getTypeArgumentsForResolvedSignature(signature) : void 0;
6380
+ transformations = [];
6381
+ for (let i = 0; i < result2.args.length; i++) {
6382
+ const arg = result2.args[i];
6383
+ const outType = typeArguments?.[i + 1];
6384
+ if (ts.isCallExpression(arg)) {
6385
+ transformations.push({
6386
+ callee: arg.expression,
6387
+ // e.g., Effect.map
6388
+ args: Array.from(arg.arguments),
6389
+ // e.g., [(x) => x + 1]
6390
+ outType,
6391
+ kind: result2.kind
6392
+ });
6393
+ } else {
6394
+ transformations.push({
6395
+ callee: arg,
6396
+ // e.g., Effect.asVoid
6397
+ args: void 0,
6398
+ outType,
6399
+ kind: result2.kind
6400
+ });
6401
+ }
6402
+ }
6403
+ flowNode = result2.node;
6404
+ childrenToTraverse = result2.args;
6405
+ } else {
6406
+ const callSignature = typeChecker.getResolvedSignature(node);
6407
+ const outType = callSignature ? typeChecker.getReturnTypeOfSignature(callSignature) : void 0;
6408
+ transformations = [{
6409
+ callee: result2.callee,
6410
+ args: void 0,
6411
+ outType,
6412
+ kind: "call"
6413
+ }];
6414
+ flowNode = node;
6415
+ }
6416
+ if (parentFlow) {
6417
+ parentFlow.transformations.unshift(...transformations);
6418
+ parentFlow.subject = {
6419
+ node: result2.subject,
6420
+ outType: typeCheckerUtils.getTypeAtLocation(result2.subject)
6421
+ };
6422
+ workQueue.push([result2.subject, parentFlow]);
6423
+ } else {
6424
+ const newFlow = {
6425
+ node: flowNode,
6426
+ subject: {
6427
+ node: result2.subject,
6428
+ outType: typeCheckerUtils.getTypeAtLocation(result2.subject)
6429
+ },
6430
+ transformations
6431
+ };
6432
+ workQueue.push([result2.subject, newFlow]);
6433
+ }
6434
+ for (const child of childrenToTraverse) {
6435
+ ts.forEachChild(child, (c) => {
6436
+ workQueue.push([c, void 0]);
6437
+ });
6438
+ }
6439
+ continue;
6440
+ }
6441
+ if (includeEffectFn) {
6442
+ const effectFnGenParsed = yield* pipe(effectFnGen(node), option);
6443
+ const effectFnUntracedGenParsed = isNone2(effectFnGenParsed) ? yield* pipe(effectFnUntracedGen(node), option) : none2();
6444
+ const effectFnNonGenParsed = isNone2(effectFnGenParsed) && isNone2(effectFnUntracedGenParsed) ? yield* pipe(effectFn(node), option) : none2();
6445
+ const isEffectFnGen = isSome2(effectFnGenParsed);
6446
+ const isEffectFnUntracedGen = isSome2(effectFnUntracedGenParsed);
6447
+ const isEffectFnNonGen = isSome2(effectFnNonGenParsed);
6448
+ const transformationKind = isEffectFnUntracedGen ? "effectFnUntraced" : "effectFn";
6449
+ if (isEffectFnGen || isEffectFnUntracedGen) {
6450
+ const effectFnParsed = isEffectFnGen ? effectFnGenParsed : effectFnUntracedGenParsed;
6451
+ if (isSome2(effectFnParsed) && effectFnParsed.value.pipeArguments.length > 0) {
6452
+ const fnResult = effectFnParsed.value;
6453
+ const pipeArgs = fnResult.pipeArguments;
6454
+ const transformations = [];
6455
+ let subjectType;
6456
+ for (let i = 0; i < pipeArgs.length; i++) {
6457
+ const arg = pipeArgs[i];
6458
+ const contextualType = typeChecker.getContextualType(arg);
6459
+ const callSigs = contextualType ? typeChecker.getSignaturesOfType(contextualType, ts.SignatureKind.Call) : [];
6460
+ const outType = callSigs.length > 0 ? typeChecker.getReturnTypeOfSignature(callSigs[0]) : void 0;
6461
+ if (i === 0 && callSigs.length > 0) {
6462
+ const params = callSigs[0].parameters;
6463
+ if (params.length > 0) {
6464
+ subjectType = typeChecker.getTypeOfSymbol(params[0]);
6465
+ }
6466
+ }
6467
+ if (ts.isCallExpression(arg)) {
6468
+ transformations.push({
6469
+ callee: arg.expression,
6470
+ args: Array.from(arg.arguments),
6471
+ outType,
6472
+ kind: transformationKind
6473
+ });
6474
+ } else {
6475
+ transformations.push({
6476
+ callee: arg,
6477
+ args: void 0,
6478
+ outType,
6479
+ kind: transformationKind
6480
+ });
6481
+ }
6482
+ }
6483
+ const newFlow = {
6484
+ node,
6485
+ subject: {
6486
+ node,
6487
+ outType: subjectType
6488
+ },
6489
+ transformations
6490
+ };
6491
+ result.push(newFlow);
6492
+ workQueue.push([fnResult.body, void 0]);
6493
+ for (const arg of pipeArgs) {
6494
+ ts.forEachChild(arg, (c) => {
6495
+ workQueue.push([c, void 0]);
6496
+ });
6497
+ }
6498
+ continue;
6499
+ }
6500
+ }
6501
+ if (isEffectFnNonGen && isSome2(effectFnNonGenParsed) && effectFnNonGenParsed.value.pipeArguments.length > 0) {
6502
+ const fnResult = effectFnNonGenParsed.value;
6503
+ const pipeArgs = fnResult.pipeArguments;
6504
+ const transformations = [];
6505
+ let subjectType;
6506
+ for (let i = 0; i < pipeArgs.length; i++) {
6507
+ const arg = pipeArgs[i];
6508
+ const contextualType = typeChecker.getContextualType(arg);
6509
+ const callSigs = contextualType ? typeChecker.getSignaturesOfType(contextualType, ts.SignatureKind.Call) : [];
6510
+ const outType = callSigs.length > 0 ? typeChecker.getReturnTypeOfSignature(callSigs[0]) : void 0;
6511
+ if (i === 0 && callSigs.length > 0) {
6512
+ const params = callSigs[0].parameters;
6513
+ if (params.length > 0) {
6514
+ subjectType = typeChecker.getTypeOfSymbol(params[0]);
6515
+ }
6516
+ }
6517
+ if (ts.isCallExpression(arg)) {
6518
+ transformations.push({
6519
+ callee: arg.expression,
6520
+ args: Array.from(arg.arguments),
6521
+ outType,
6522
+ kind: "effectFn"
6523
+ });
6524
+ } else {
6525
+ transformations.push({
6526
+ callee: arg,
6527
+ args: void 0,
6528
+ outType,
6529
+ kind: "effectFn"
6530
+ });
6531
+ }
6532
+ }
6533
+ const newFlow = {
6534
+ node,
6535
+ subject: {
6536
+ node,
6537
+ outType: subjectType
6538
+ },
6539
+ transformations
6540
+ };
6541
+ result.push(newFlow);
6542
+ const regularFn = fnResult.regularFunction;
6543
+ if (ts.isArrowFunction(regularFn)) {
6544
+ if (ts.isBlock(regularFn.body)) {
6545
+ workQueue.push([regularFn.body, void 0]);
6546
+ } else {
6547
+ workQueue.push([regularFn.body, void 0]);
6548
+ }
6549
+ } else if (regularFn.body) {
6550
+ workQueue.push([regularFn.body, void 0]);
6551
+ }
6552
+ for (const arg of pipeArgs) {
6553
+ ts.forEachChild(arg, (c) => {
6554
+ workQueue.push([c, void 0]);
6555
+ });
6556
+ }
6557
+ continue;
6558
+ }
6559
+ }
6560
+ }
6561
+ if (parentFlow && parentFlow.transformations.length > 0) {
6562
+ result.push(parentFlow);
6563
+ }
6564
+ ts.forEachChild(node, (child) => {
6565
+ workQueue.push([child, void 0]);
6566
+ });
6567
+ }
6568
+ result.sort((a, b) => a.node.pos - b.node.pos);
6569
+ return result;
6570
+ }),
6571
+ `TypeParser.pipingFlows(${includeEffectFn})`,
6572
+ (sourceFile) => sourceFile
6573
+ );
6574
+ const reconstructPipingFlow = (flow2) => {
6575
+ if (flow2.transformations.length > 0 && flow2.transformations.every((t) => t.kind === "effectFn" || t.kind === "effectFnUntraced")) {
6576
+ return flow2.subject.node;
6577
+ }
6578
+ let result = flow2.subject.node;
6579
+ for (const t of flow2.transformations) {
6580
+ if (t.kind === "call") {
6581
+ result = ts.factory.createCallExpression(
6582
+ t.callee,
6583
+ void 0,
6584
+ [result]
6585
+ );
6586
+ } else if (t.kind === "effectFn" || t.kind === "effectFnUntraced") {
6587
+ continue;
6588
+ } else {
6589
+ if (t.args) {
6590
+ const transformCall = ts.factory.createCallExpression(
6591
+ t.callee,
6592
+ void 0,
6593
+ t.args
6594
+ );
6595
+ result = ts.factory.createCallExpression(
6596
+ transformCall,
6597
+ void 0,
6598
+ [result]
6599
+ );
6600
+ } else {
6601
+ result = ts.factory.createCallExpression(
6602
+ t.callee,
6603
+ void 0,
6604
+ [result]
6605
+ );
6606
+ }
6607
+ }
6608
+ }
6609
+ return result;
6610
+ };
6143
6611
  return {
6144
6612
  isNodeReferenceToEffectModuleApi,
6145
6613
  isNodeReferenceToEffectSchemaModuleApi,
6614
+ isNodeReferenceToEffectParseResultModuleApi,
6146
6615
  isNodeReferenceToEffectDataModuleApi,
6147
6616
  isNodeReferenceToEffectContextModuleApi,
6148
6617
  isNodeReferenceToEffectSqlModelModuleApi,
@@ -6156,12 +6625,15 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
6156
6625
  effectGen,
6157
6626
  effectFnUntracedGen,
6158
6627
  effectFnGen,
6628
+ findEnclosingScopes,
6629
+ effectFn,
6159
6630
  extendsCauseYieldableError,
6160
6631
  unnecessaryEffectGen: unnecessaryEffectGen2,
6161
6632
  effectSchemaType,
6162
6633
  contextTag,
6163
6634
  pipeableType,
6164
6635
  pipeCall,
6636
+ singleArgCall,
6165
6637
  scopeType,
6166
6638
  promiseLike,
6167
6639
  extendsEffectTag,
@@ -6173,7 +6645,11 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
6173
6645
  extendsDataTaggedError,
6174
6646
  extendsDataTaggedClass,
6175
6647
  extendsSchemaTaggedRequest,
6176
- extendsEffectSqlModelClass
6648
+ extendsEffectSqlModelClass,
6649
+ lazyExpression,
6650
+ emptyFunction,
6651
+ pipingFlows,
6652
+ reconstructPipingFlow
6177
6653
  };
6178
6654
  }
6179
6655
 
@@ -7521,48 +7997,45 @@ var catchAllToMapError = createDiagnostic({
7521
7997
  return none2();
7522
7998
  });
7523
7999
  };
7524
- const nodeToVisit = [];
7525
- const appendNodeToVisit = (node) => {
7526
- nodeToVisit.push(node);
7527
- return void 0;
7528
- };
7529
- ts.forEachChild(sourceFile, appendNodeToVisit);
7530
- while (nodeToVisit.length > 0) {
7531
- const node = nodeToVisit.shift();
7532
- ts.forEachChild(node, appendNodeToVisit);
7533
- if (ts.isCallExpression(node)) {
8000
+ const flows = yield* typeParser.pipingFlows(true)(sourceFile);
8001
+ for (const flow2 of flows) {
8002
+ for (const transformation of flow2.transformations) {
8003
+ if (!transformation.args || transformation.args.length === 0) {
8004
+ continue;
8005
+ }
7534
8006
  const isCatchAllCall = yield* pipe(
7535
- typeParser.isNodeReferenceToEffectModuleApi("catchAll")(node.expression),
8007
+ typeParser.isNodeReferenceToEffectModuleApi("catchAll")(transformation.callee),
7536
8008
  option
7537
8009
  );
7538
- if (isSome2(isCatchAllCall)) {
7539
- const callback = node.arguments[0];
7540
- if (!callback) continue;
7541
- const functionBody = getFunctionBody(callback);
7542
- if (!functionBody) continue;
7543
- const failCallInfo = yield* getEffectFailCallInfo(functionBody);
7544
- if (isNone2(failCallInfo)) continue;
7545
- const { failArg, failCall } = failCallInfo.value;
7546
- report({
7547
- location: node.expression,
7548
- messageText: `You can use Effect.mapError instead of Effect.catchAll + Effect.fail to transform the error type.`,
7549
- fixes: [{
7550
- fixName: "catchAllToMapError_fix",
7551
- description: "Replace with Effect.mapError",
7552
- apply: gen(function* () {
7553
- const changeTracker = yield* service(ChangeTracker);
7554
- if (ts.isPropertyAccessExpression(node.expression)) {
7555
- changeTracker.replaceNode(
7556
- sourceFile,
7557
- node.expression.name,
7558
- ts.factory.createIdentifier("mapError")
7559
- );
7560
- }
7561
- changeTracker.replaceNode(sourceFile, failCall, failArg);
7562
- })
7563
- }]
7564
- });
8010
+ if (isNone2(isCatchAllCall)) {
8011
+ continue;
7565
8012
  }
8013
+ const callback = transformation.args[0];
8014
+ if (!callback) continue;
8015
+ const functionBody = getFunctionBody(callback);
8016
+ if (!functionBody) continue;
8017
+ const failCallInfo = yield* getEffectFailCallInfo(functionBody);
8018
+ if (isNone2(failCallInfo)) continue;
8019
+ const { failArg, failCall } = failCallInfo.value;
8020
+ report({
8021
+ location: transformation.callee,
8022
+ messageText: `You can use Effect.mapError instead of Effect.catchAll + Effect.fail to transform the error type.`,
8023
+ fixes: [{
8024
+ fixName: "catchAllToMapError_fix",
8025
+ description: "Replace with Effect.mapError",
8026
+ apply: gen(function* () {
8027
+ const changeTracker = yield* service(ChangeTracker);
8028
+ if (ts.isPropertyAccessExpression(transformation.callee)) {
8029
+ changeTracker.replaceNode(
8030
+ sourceFile,
8031
+ transformation.callee.name,
8032
+ ts.factory.createIdentifier("mapError")
8033
+ );
8034
+ }
8035
+ changeTracker.replaceNode(sourceFile, failCall, failArg);
8036
+ })
8037
+ }]
8038
+ });
7566
8039
  }
7567
8040
  }
7568
8041
  })
@@ -7577,66 +8050,39 @@ var catchUnfailableEffect = createDiagnostic({
7577
8050
  apply: fn("catchUnfailableEffect.apply")(function* (sourceFile, report) {
7578
8051
  const ts = yield* service(TypeScriptApi);
7579
8052
  const typeParser = yield* service(TypeParser);
7580
- const typeChecker = yield* service(TypeCheckerApi);
7581
- const typeCheckerUtils = yield* service(TypeCheckerUtils);
7582
- const nodeToVisit = [];
7583
- const appendNodeToVisit = (node) => {
7584
- nodeToVisit.push(node);
7585
- return void 0;
7586
- };
7587
- ts.forEachChild(sourceFile, appendNodeToVisit);
7588
- while (nodeToVisit.length > 0) {
7589
- const node = nodeToVisit.shift();
7590
- ts.forEachChild(node, appendNodeToVisit);
7591
- if (ts.isCallExpression(node)) {
7592
- const catchFunctions = ["catchAll", "catch", "catchIf", "catchSome", "catchTag", "catchTags"];
8053
+ const catchFunctions = ["catchAll", "catch", "catchIf", "catchSome", "catchTag", "catchTags"];
8054
+ const flows = yield* typeParser.pipingFlows(true)(sourceFile);
8055
+ for (const flow2 of flows) {
8056
+ for (let i = 0; i < flow2.transformations.length; i++) {
8057
+ const transformation = flow2.transformations[i];
8058
+ if (!transformation.args || transformation.args.length === 0) {
8059
+ continue;
8060
+ }
7593
8061
  const isCatchCall = yield* pipe(
7594
8062
  firstSuccessOf(
7595
- catchFunctions.map((catchFn) => typeParser.isNodeReferenceToEffectModuleApi(catchFn)(node.expression))
8063
+ catchFunctions.map((catchFn) => typeParser.isNodeReferenceToEffectModuleApi(catchFn)(transformation.callee))
7596
8064
  ),
7597
8065
  option
7598
8066
  );
7599
- if (isSome2(isCatchCall)) {
7600
- const parent = node.parent;
7601
- if (parent && ts.isCallExpression(parent)) {
7602
- const pipeCallResult = yield* pipe(
7603
- typeParser.pipeCall(parent),
7604
- option
7605
- );
7606
- if (isSome2(pipeCallResult)) {
7607
- const { args: args2, node: pipeCallNode, subject } = pipeCallResult.value;
7608
- const argIndex = args2.findIndex((arg) => arg === node);
7609
- if (argIndex !== -1) {
7610
- let effectTypeToCheck;
7611
- if (argIndex === 0) {
7612
- effectTypeToCheck = typeCheckerUtils.getTypeAtLocation(subject);
7613
- } else {
7614
- const signature = typeChecker.getResolvedSignature(pipeCallNode);
7615
- if (signature) {
7616
- const typeArguments = typeChecker.getTypeArgumentsForResolvedSignature(signature);
7617
- if (typeArguments && typeArguments.length > argIndex) {
7618
- effectTypeToCheck = typeArguments[argIndex];
7619
- }
7620
- }
7621
- }
7622
- if (effectTypeToCheck) {
7623
- const effectType = yield* pipe(
7624
- typeParser.effectType(effectTypeToCheck, node),
7625
- option
7626
- );
7627
- if (isSome2(effectType)) {
7628
- const { E } = effectType.value;
7629
- if (E.flags & ts.TypeFlags.Never) {
7630
- report({
7631
- location: node.expression,
7632
- messageText: `Looks like the previous effect never fails, so probably this error handling will never be triggered.`,
7633
- fixes: []
7634
- });
7635
- }
7636
- }
7637
- }
7638
- }
7639
- }
8067
+ if (isNone2(isCatchCall)) {
8068
+ continue;
8069
+ }
8070
+ const inputType = i === 0 ? flow2.subject.outType : flow2.transformations[i - 1].outType;
8071
+ if (!inputType) {
8072
+ continue;
8073
+ }
8074
+ const effectType = yield* pipe(
8075
+ typeParser.effectType(inputType, transformation.callee),
8076
+ option
8077
+ );
8078
+ if (isSome2(effectType)) {
8079
+ const { E } = effectType.value;
8080
+ if (E.flags & ts.TypeFlags.Never) {
8081
+ report({
8082
+ location: transformation.callee,
8083
+ messageText: `Looks like the previous effect never fails, so probably this error handling will never be triggered.`,
8084
+ fixes: []
8085
+ });
7640
8086
  }
7641
8087
  }
7642
8088
  }
@@ -7879,6 +8325,269 @@ ${versions.map((version) => `- found ${version} at ${resolvedPackages[packageNam
7879
8325
  })
7880
8326
  });
7881
8327
 
8328
+ // src/diagnostics/effectFnOpportunity.ts
8329
+ var effectFnOpportunity = createDiagnostic({
8330
+ name: "effectFnOpportunity",
8331
+ code: 41,
8332
+ description: "Suggests using Effect.fn for functions that returns an Effect",
8333
+ severity: "suggestion",
8334
+ apply: fn("effectFnOpportunity.apply")(function* (sourceFile, report) {
8335
+ const ts = yield* service(TypeScriptApi);
8336
+ const typeChecker = yield* service(TypeCheckerApi);
8337
+ const typeCheckerUtils = yield* service(TypeCheckerUtils);
8338
+ const typeParser = yield* service(TypeParser);
8339
+ const tsUtils = yield* service(TypeScriptUtils);
8340
+ const sourceEffectModuleName = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
8341
+ sourceFile,
8342
+ "effect",
8343
+ "Effect"
8344
+ ) || "Effect";
8345
+ const findSingleReturnStatement = (block) => {
8346
+ if (block.statements.length !== 1) return void 0;
8347
+ const statement = block.statements[0];
8348
+ if (!ts.isReturnStatement(statement)) return void 0;
8349
+ return statement;
8350
+ };
8351
+ const getBodyExpression = (fnNode) => {
8352
+ if (ts.isArrowFunction(fnNode)) {
8353
+ if (ts.isBlock(fnNode.body)) {
8354
+ return findSingleReturnStatement(fnNode.body)?.expression;
8355
+ }
8356
+ return fnNode.body;
8357
+ } else if ((ts.isFunctionExpression(fnNode) || ts.isFunctionDeclaration(fnNode)) && fnNode.body) {
8358
+ return findSingleReturnStatement(fnNode.body)?.expression;
8359
+ }
8360
+ return void 0;
8361
+ };
8362
+ const getNameIdentifier = (node) => {
8363
+ if (ts.isFunctionDeclaration(node) && node.name) {
8364
+ return node.name;
8365
+ }
8366
+ if (node.parent && ts.isVariableDeclaration(node.parent) && ts.isIdentifier(node.parent.name)) {
8367
+ return node.parent.name;
8368
+ }
8369
+ if (node.parent && ts.isPropertyAssignment(node.parent)) {
8370
+ const name = node.parent.name;
8371
+ if (ts.isIdentifier(name) || ts.isStringLiteral(name)) {
8372
+ return name;
8373
+ }
8374
+ }
8375
+ if (node.parent && ts.isPropertyDeclaration(node.parent)) {
8376
+ const name = node.parent.name;
8377
+ if (ts.isIdentifier(name)) {
8378
+ return name;
8379
+ }
8380
+ }
8381
+ return void 0;
8382
+ };
8383
+ const areParametersReferencedIn = (fnNode, nodes2) => {
8384
+ if (fnNode.parameters.length === 0 || nodes2.length === 0) return false;
8385
+ const firstParam = fnNode.parameters[0];
8386
+ const lastParam = fnNode.parameters[fnNode.parameters.length - 1];
8387
+ const paramsStart = firstParam.pos;
8388
+ const paramsEnd = lastParam.end;
8389
+ const isSymbolDeclaredInParams = (symbol3) => {
8390
+ const declarations = symbol3.declarations;
8391
+ if (!declarations) return false;
8392
+ return declarations.some((decl) => decl.pos >= paramsStart && decl.end <= paramsEnd);
8393
+ };
8394
+ const nodesToVisit = [...nodes2];
8395
+ while (nodesToVisit.length > 0) {
8396
+ const node = nodesToVisit.shift();
8397
+ if (ts.isIdentifier(node)) {
8398
+ const symbol3 = typeChecker.getSymbolAtLocation(node);
8399
+ if (symbol3 && isSymbolDeclaredInParams(symbol3)) {
8400
+ return true;
8401
+ }
8402
+ }
8403
+ if (ts.isShorthandPropertyAssignment(node)) {
8404
+ const valueSymbol = typeChecker.getShorthandAssignmentValueSymbol(node);
8405
+ if (valueSymbol && isSymbolDeclaredInParams(valueSymbol)) {
8406
+ return true;
8407
+ }
8408
+ }
8409
+ ts.forEachChild(node, (child) => {
8410
+ nodesToVisit.push(child);
8411
+ return void 0;
8412
+ });
8413
+ }
8414
+ return false;
8415
+ };
8416
+ const tryParseGenOpportunity = (fnNode) => gen(function* () {
8417
+ const bodyExpression = getBodyExpression(fnNode);
8418
+ if (!bodyExpression) return yield* TypeParserIssue.issue;
8419
+ const { pipeArguments: pipeArguments2, subject } = yield* pipe(
8420
+ typeParser.pipeCall(bodyExpression),
8421
+ map8(({ args: args2, subject: subject2 }) => ({ subject: subject2, pipeArguments: args2 })),
8422
+ orElse2(() => succeed({ subject: bodyExpression, pipeArguments: [] }))
8423
+ );
8424
+ const { effectModule, generatorFunction } = yield* typeParser.effectGen(subject);
8425
+ const effectModuleName = ts.isIdentifier(effectModule) ? ts.idText(effectModule) : sourceEffectModuleName;
8426
+ return { effectModuleName, generatorFunction, pipeArguments: pipeArguments2 };
8427
+ });
8428
+ const isInsideEffectFn = (fnNode) => {
8429
+ const parent = fnNode.parent;
8430
+ if (!parent || !ts.isCallExpression(parent)) {
8431
+ return succeed(false);
8432
+ }
8433
+ if (parent.arguments[0] !== fnNode) {
8434
+ return succeed(false);
8435
+ }
8436
+ return pipe(
8437
+ typeParser.effectFn(parent),
8438
+ orElse2(() => typeParser.effectFnGen(parent)),
8439
+ orElse2(() => typeParser.effectFnUntracedGen(parent)),
8440
+ map8(() => true),
8441
+ orElse2(() => succeed(false))
8442
+ );
8443
+ };
8444
+ const parseEffectFnOpportunityTarget = (node) => gen(function* () {
8445
+ if (!ts.isFunctionExpression(node) && !ts.isArrowFunction(node) && !ts.isFunctionDeclaration(node)) {
8446
+ return yield* TypeParserIssue.issue;
8447
+ }
8448
+ if ((ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) && node.asteriskToken) {
8449
+ return yield* TypeParserIssue.issue;
8450
+ }
8451
+ if (ts.isFunctionExpression(node) && node.name) {
8452
+ return yield* TypeParserIssue.issue;
8453
+ }
8454
+ if (yield* isInsideEffectFn(node)) {
8455
+ return yield* TypeParserIssue.issue;
8456
+ }
8457
+ const functionType = typeChecker.getTypeAtLocation(node);
8458
+ if (!functionType) return yield* TypeParserIssue.issue;
8459
+ const callSignatures = typeChecker.getSignaturesOfType(functionType, ts.SignatureKind.Call);
8460
+ if (callSignatures.length !== 1) return yield* TypeParserIssue.issue;
8461
+ const signature = callSignatures[0];
8462
+ const returnType = typeChecker.getReturnTypeOfSignature(signature);
8463
+ const unionMembers = typeCheckerUtils.unrollUnionMembers(returnType);
8464
+ yield* all(...unionMembers.map((member) => typeParser.strictEffectType(member, node)));
8465
+ const nameIdentifier = getNameIdentifier(node);
8466
+ const traceName = nameIdentifier ? ts.isIdentifier(nameIdentifier) ? ts.idText(nameIdentifier) : nameIdentifier.text : void 0;
8467
+ if (!traceName) return yield* TypeParserIssue.issue;
8468
+ const opportunity = yield* pipe(
8469
+ tryParseGenOpportunity(node),
8470
+ orElse2(
8471
+ () => succeed({ effectModuleName: sourceEffectModuleName, pipeArguments: [], generatorFunction: void 0 })
8472
+ )
8473
+ );
8474
+ return {
8475
+ node,
8476
+ nameIdentifier,
8477
+ effectModuleName: opportunity.effectModuleName,
8478
+ traceName,
8479
+ pipeArguments: opportunity.pipeArguments,
8480
+ generatorFunction: opportunity.generatorFunction,
8481
+ hasParamsInPipeArgs: areParametersReferencedIn(node, opportunity.pipeArguments)
8482
+ };
8483
+ });
8484
+ const getFunctionBodyBlock = (node) => {
8485
+ if (ts.isArrowFunction(node)) {
8486
+ if (ts.isBlock(node.body)) {
8487
+ return node.body;
8488
+ }
8489
+ return ts.factory.createBlock([ts.factory.createReturnStatement(node.body)], true);
8490
+ }
8491
+ return node.body;
8492
+ };
8493
+ const isGeneratorFunction = (node) => {
8494
+ if (ts.isArrowFunction(node)) return false;
8495
+ return node.asteriskToken !== void 0;
8496
+ };
8497
+ const createEffectFnNode = (originalNode, innerFunction, effectModuleName, traceName, pipeArguments2) => {
8498
+ const isGenerator = isGeneratorFunction(innerFunction);
8499
+ const newFunction = ts.factory.createFunctionExpression(
8500
+ void 0,
8501
+ isGenerator ? ts.factory.createToken(ts.SyntaxKind.AsteriskToken) : void 0,
8502
+ void 0,
8503
+ originalNode.typeParameters,
8504
+ originalNode.parameters,
8505
+ void 0,
8506
+ getFunctionBodyBlock(innerFunction)
8507
+ );
8508
+ let fnExpression = ts.factory.createPropertyAccessExpression(
8509
+ ts.factory.createIdentifier(effectModuleName),
8510
+ "fn"
8511
+ );
8512
+ if (traceName) {
8513
+ fnExpression = ts.factory.createCallExpression(
8514
+ fnExpression,
8515
+ void 0,
8516
+ [ts.factory.createStringLiteral(traceName)]
8517
+ );
8518
+ }
8519
+ const effectFnCall = ts.factory.createCallExpression(fnExpression, void 0, [newFunction, ...pipeArguments2]);
8520
+ if (ts.isFunctionDeclaration(originalNode)) {
8521
+ return tsUtils.tryPreserveDeclarationSemantics(originalNode, effectFnCall, false);
8522
+ }
8523
+ return effectFnCall;
8524
+ };
8525
+ const createEffectFnUntracedNode = (originalNode, innerFunction, effectModuleName, pipeArguments2) => {
8526
+ const isGenerator = isGeneratorFunction(innerFunction);
8527
+ const newFunction = ts.factory.createFunctionExpression(
8528
+ void 0,
8529
+ isGenerator ? ts.factory.createToken(ts.SyntaxKind.AsteriskToken) : void 0,
8530
+ void 0,
8531
+ originalNode.typeParameters,
8532
+ originalNode.parameters,
8533
+ void 0,
8534
+ getFunctionBodyBlock(innerFunction)
8535
+ );
8536
+ const effectFnCall = ts.factory.createCallExpression(
8537
+ ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(effectModuleName), "fnUntraced"),
8538
+ void 0,
8539
+ [newFunction, ...pipeArguments2]
8540
+ );
8541
+ if (ts.isFunctionDeclaration(originalNode)) {
8542
+ return tsUtils.tryPreserveDeclarationSemantics(originalNode, effectFnCall, false);
8543
+ }
8544
+ return effectFnCall;
8545
+ };
8546
+ const nodeToVisit = [];
8547
+ const appendNodeToVisit = (node) => {
8548
+ nodeToVisit.push(node);
8549
+ return void 0;
8550
+ };
8551
+ ts.forEachChild(sourceFile, appendNodeToVisit);
8552
+ while (nodeToVisit.length > 0) {
8553
+ const node = nodeToVisit.shift();
8554
+ ts.forEachChild(node, appendNodeToVisit);
8555
+ const target = yield* pipe(parseEffectFnOpportunityTarget(node), option);
8556
+ if (isNone2(target)) continue;
8557
+ if (target.value.hasParamsInPipeArgs) continue;
8558
+ const { effectModuleName, nameIdentifier, node: targetNode, pipeArguments: pipeArguments2, traceName } = target.value;
8559
+ const innerFunction = target.value.generatorFunction ?? targetNode;
8560
+ const fixes = [];
8561
+ fixes.push({
8562
+ fixName: "effectFnOpportunity_toEffectFn",
8563
+ description: traceName ? `Convert to Effect.fn("${traceName}")` : "Convert to Effect.fn",
8564
+ apply: gen(function* () {
8565
+ const changeTracker = yield* service(ChangeTracker);
8566
+ const newNode = createEffectFnNode(targetNode, innerFunction, effectModuleName, traceName, pipeArguments2);
8567
+ changeTracker.replaceNode(sourceFile, targetNode, newNode);
8568
+ })
8569
+ });
8570
+ if (target.value.generatorFunction) {
8571
+ fixes.push({
8572
+ fixName: "effectFnOpportunity_toEffectFnUntraced",
8573
+ description: "Convert to Effect.fnUntraced",
8574
+ apply: gen(function* () {
8575
+ const changeTracker = yield* service(ChangeTracker);
8576
+ const newNode = createEffectFnUntracedNode(targetNode, innerFunction, effectModuleName, pipeArguments2);
8577
+ changeTracker.replaceNode(sourceFile, targetNode, newNode);
8578
+ })
8579
+ });
8580
+ }
8581
+ const pipeArgsSuffix = pipeArguments2.length > 0 ? ` Effect.fn also accepts the piped transformations as additional arguments.` : ``;
8582
+ report({
8583
+ location: nameIdentifier ?? targetNode,
8584
+ messageText: target.value.generatorFunction ? `This function could benefit from Effect.fn's automatic tracing and concise syntax, or Effect.fnUntraced to get just a more concise syntax.${pipeArgsSuffix}` : `This function could benefit from Effect.fn's automatic tracing and concise syntax.${pipeArgsSuffix}`,
8585
+ fixes
8586
+ });
8587
+ }
8588
+ })
8589
+ });
8590
+
7882
8591
  // src/diagnostics/effectGenUsesAdapter.ts
7883
8592
  var effectGenUsesAdapter = createDiagnostic({
7884
8593
  name: "effectGenUsesAdapter",
@@ -7966,6 +8675,70 @@ var effectInVoidSuccess = createDiagnostic({
7966
8675
  })
7967
8676
  });
7968
8677
 
8678
+ // src/diagnostics/effectMapVoid.ts
8679
+ var effectMapVoid = createDiagnostic({
8680
+ name: "effectMapVoid",
8681
+ code: 40,
8682
+ description: "Suggests using Effect.asVoid instead of Effect.map(() => void 0), Effect.map(() => undefined), or Effect.map(() => {})",
8683
+ severity: "suggestion",
8684
+ apply: fn("effectMapVoid.apply")(function* (sourceFile, report) {
8685
+ const ts = yield* service(TypeScriptApi);
8686
+ const typeParser = yield* service(TypeParser);
8687
+ const tsUtils = yield* service(TypeScriptUtils);
8688
+ const nodeToVisit = [];
8689
+ const appendNodeToVisit = (node) => {
8690
+ nodeToVisit.push(node);
8691
+ return void 0;
8692
+ };
8693
+ ts.forEachChild(sourceFile, appendNodeToVisit);
8694
+ while (nodeToVisit.length > 0) {
8695
+ const node = nodeToVisit.shift();
8696
+ ts.forEachChild(node, appendNodeToVisit);
8697
+ if (ts.isCallExpression(node)) {
8698
+ const isMapCall = yield* pipe(
8699
+ typeParser.isNodeReferenceToEffectModuleApi("map")(node.expression),
8700
+ option
8701
+ );
8702
+ if (isSome2(isMapCall)) {
8703
+ const callback = node.arguments[0];
8704
+ if (!callback) continue;
8705
+ const match3 = yield* pipe(
8706
+ typeParser.emptyFunction(callback),
8707
+ orElse2(
8708
+ () => pipe(
8709
+ typeParser.lazyExpression(callback),
8710
+ flatMap4(
8711
+ (lazy) => tsUtils.isVoidExpression(lazy.expression) ? succeed(lazy) : typeParserIssue("Expression is not void")
8712
+ )
8713
+ )
8714
+ ),
8715
+ option
8716
+ );
8717
+ if (isNone2(match3)) continue;
8718
+ report({
8719
+ location: node.expression,
8720
+ messageText: "Effect.asVoid can be used instead to discard the success value",
8721
+ fixes: [{
8722
+ fixName: "effectMapVoid_fix",
8723
+ description: "Replace with Effect.asVoid",
8724
+ apply: gen(function* () {
8725
+ const changeTracker = yield* service(ChangeTracker);
8726
+ if (ts.isPropertyAccessExpression(node.expression)) {
8727
+ const newNode = ts.factory.createPropertyAccessExpression(
8728
+ node.expression.expression,
8729
+ ts.factory.createIdentifier("asVoid")
8730
+ );
8731
+ changeTracker.replaceNode(sourceFile, node, newNode);
8732
+ }
8733
+ })
8734
+ }]
8735
+ });
8736
+ }
8737
+ }
8738
+ }
8739
+ })
8740
+ });
8741
+
7969
8742
  // src/diagnostics/floatingEffect.ts
7970
8743
  var floatingEffect = createDiagnostic({
7971
8744
  name: "floatingEffect",
@@ -8574,75 +9347,153 @@ var missedPipeableOpportunity = createDiagnostic({
8574
9347
  apply: fn("missedPipeableOpportunity.apply")(function* (sourceFile, report) {
8575
9348
  const ts = yield* service(TypeScriptApi);
8576
9349
  const typeChecker = yield* service(TypeCheckerApi);
8577
- const typeCheckerUtils = yield* service(TypeCheckerUtils);
8578
9350
  const typeParser = yield* service(TypeParser);
8579
9351
  const options = yield* service(LanguageServicePluginOptions);
8580
- const nodeToVisit = [sourceFile];
8581
- const prependNodeToVisit = (node) => {
8582
- nodeToVisit.unshift(node);
8583
- return void 0;
9352
+ const isSafelyPipeableCallee = (callee) => {
9353
+ if (ts.isCallExpression(callee)) {
9354
+ return true;
9355
+ }
9356
+ if (ts.isArrowFunction(callee)) {
9357
+ return true;
9358
+ }
9359
+ if (ts.isFunctionExpression(callee)) {
9360
+ return true;
9361
+ }
9362
+ if (ts.isParenthesizedExpression(callee)) {
9363
+ return isSafelyPipeableCallee(callee.expression);
9364
+ }
9365
+ if (ts.isIdentifier(callee)) {
9366
+ const symbol3 = typeChecker.getSymbolAtLocation(callee);
9367
+ if (!symbol3) return false;
9368
+ if (symbol3.flags & (ts.SymbolFlags.Module | ts.SymbolFlags.Namespace | ts.SymbolFlags.ValueModule)) {
9369
+ return true;
9370
+ }
9371
+ const declarations = symbol3.declarations;
9372
+ if (declarations && declarations.length > 0) {
9373
+ const decl = declarations[0];
9374
+ if (ts.isFunctionDeclaration(decl) || ts.isVariableDeclaration(decl) || ts.isImportSpecifier(decl) || ts.isImportClause(decl) || ts.isNamespaceImport(decl)) {
9375
+ return true;
9376
+ }
9377
+ }
9378
+ return false;
9379
+ }
9380
+ if (ts.isPropertyAccessExpression(callee)) {
9381
+ const subject = callee.expression;
9382
+ const symbol3 = typeChecker.getSymbolAtLocation(subject);
9383
+ if (!symbol3) return false;
9384
+ if (symbol3.flags & (ts.SymbolFlags.Module | ts.SymbolFlags.Namespace | ts.SymbolFlags.ValueModule)) {
9385
+ return true;
9386
+ }
9387
+ const declarations = symbol3.declarations;
9388
+ if (declarations && declarations.length > 0) {
9389
+ const decl = declarations[0];
9390
+ if (ts.isNamespaceImport(decl) || ts.isSourceFile(decl) || ts.isModuleDeclaration(decl)) {
9391
+ return true;
9392
+ }
9393
+ }
9394
+ return false;
9395
+ }
9396
+ return false;
8584
9397
  };
8585
- const callChainNodes = /* @__PURE__ */ new WeakMap();
8586
- while (nodeToVisit.length > 0) {
8587
- const node = nodeToVisit.shift();
8588
- if (ts.isCallExpression(node) && node.arguments.length === 1) {
8589
- const isPipeCall = yield* pipe(typeParser.pipeCall(node), orElse2(() => void_));
8590
- if (!isPipeCall) {
8591
- const resolvedSignature = typeChecker.getResolvedSignature(node);
8592
- if (resolvedSignature) {
8593
- const returnType = typeChecker.getReturnTypeOfSignature(resolvedSignature);
8594
- if (returnType) {
8595
- const callSignatures = typeChecker.getSignaturesOfType(returnType, ts.SignatureKind.Call);
8596
- if (callSignatures.length === 0) {
8597
- const parentChain = callChainNodes.get(node) || [];
8598
- callChainNodes.set(node.arguments[0], parentChain.concat(node));
8599
- }
8600
- }
9398
+ const flows = yield* typeParser.pipingFlows(false)(sourceFile);
9399
+ for (const flow2 of flows) {
9400
+ if (flow2.transformations.length < options.pipeableMinArgCount) {
9401
+ continue;
9402
+ }
9403
+ const finalType = flow2.transformations[flow2.transformations.length - 1].outType;
9404
+ if (!finalType) {
9405
+ continue;
9406
+ }
9407
+ const callSigs = typeChecker.getSignaturesOfType(finalType, ts.SignatureKind.Call);
9408
+ if (callSigs.length > 0) {
9409
+ continue;
9410
+ }
9411
+ const isPipeableAtIndex = function* (index) {
9412
+ if (index === 0) {
9413
+ const subjectType = flow2.subject.outType;
9414
+ if (!subjectType) return false;
9415
+ const result = yield* pipe(
9416
+ typeParser.pipeableType(subjectType, flow2.subject.node),
9417
+ option
9418
+ );
9419
+ return result._tag === "Some";
9420
+ } else {
9421
+ const t = flow2.transformations[index - 1];
9422
+ if (!t.outType) return false;
9423
+ const result = yield* pipe(
9424
+ typeParser.pipeableType(t.outType, flow2.node),
9425
+ option
9426
+ );
9427
+ return result._tag === "Some";
9428
+ }
9429
+ };
9430
+ let searchStartIndex = 0;
9431
+ while (searchStartIndex <= flow2.transformations.length) {
9432
+ let firstPipeableIndex = -1;
9433
+ for (let i = searchStartIndex; i <= flow2.transformations.length; i++) {
9434
+ if (yield* isPipeableAtIndex(i)) {
9435
+ firstPipeableIndex = i;
9436
+ break;
8601
9437
  }
8602
9438
  }
8603
- } else if (callChainNodes.has(node) && ts.isExpression(node)) {
8604
- const parentChain = (callChainNodes.get(node) || []).slice();
8605
- const originalParentChain = parentChain.slice();
8606
- while (parentChain.length > options.pipeableMinArgCount) {
8607
- const subject = parentChain.pop();
8608
- const resultType = typeCheckerUtils.getTypeAtLocation(subject);
8609
- if (!resultType) continue;
8610
- const pipeableType = yield* pipe(typeParser.pipeableType(resultType, subject), orElse2(() => void_));
8611
- if (pipeableType) {
8612
- report({
8613
- location: parentChain[0],
8614
- messageText: `Nested function calls can be converted to pipeable style for better readability.`,
8615
- fixes: [{
8616
- fixName: "missedPipeableOpportunity_fix",
8617
- description: "Convert to pipe style",
8618
- apply: gen(function* () {
8619
- const changeTracker = yield* service(ChangeTracker);
8620
- changeTracker.replaceNode(
8621
- sourceFile,
8622
- parentChain[0],
8623
- ts.factory.createCallExpression(
8624
- ts.factory.createPropertyAccessExpression(
8625
- subject,
8626
- "pipe"
8627
- ),
8628
- void 0,
8629
- pipe(
8630
- parentChain,
8631
- filter(ts.isCallExpression),
8632
- map4((call) => call.expression),
8633
- reverse2
8634
- )
8635
- )
8636
- );
8637
- })
8638
- }]
8639
- });
8640
- originalParentChain.forEach((node2) => callChainNodes.delete(node2));
9439
+ if (firstPipeableIndex === -1) {
9440
+ break;
9441
+ }
9442
+ const pipeableTransformations = [];
9443
+ for (let i = firstPipeableIndex; i < flow2.transformations.length; i++) {
9444
+ const t = flow2.transformations[i];
9445
+ if (!isSafelyPipeableCallee(t.callee)) {
8641
9446
  break;
8642
9447
  }
9448
+ pipeableTransformations.push(t);
9449
+ }
9450
+ const callKindCount = pipeableTransformations.filter((t) => t.kind === "call").length;
9451
+ if (callKindCount >= options.pipeableMinArgCount) {
9452
+ const pipeableEndIndex = firstPipeableIndex + pipeableTransformations.length;
9453
+ const pipeableSubjectNode = firstPipeableIndex === 0 ? flow2.subject.node : typeParser.reconstructPipingFlow({
9454
+ subject: flow2.subject,
9455
+ transformations: flow2.transformations.slice(0, firstPipeableIndex)
9456
+ });
9457
+ const afterTransformations = flow2.transformations.slice(pipeableEndIndex);
9458
+ report({
9459
+ location: flow2.node,
9460
+ messageText: `Nested function calls can be converted to pipeable style for better readability.`,
9461
+ fixes: [{
9462
+ fixName: "missedPipeableOpportunity_fix",
9463
+ description: "Convert to pipe style",
9464
+ apply: gen(function* () {
9465
+ const changeTracker = yield* service(ChangeTracker);
9466
+ const pipeArgs = pipeableTransformations.map((t) => {
9467
+ if (t.args) {
9468
+ return ts.factory.createCallExpression(
9469
+ t.callee,
9470
+ void 0,
9471
+ t.args
9472
+ );
9473
+ } else {
9474
+ return t.callee;
9475
+ }
9476
+ });
9477
+ const pipeNode = ts.factory.createCallExpression(
9478
+ ts.factory.createPropertyAccessExpression(
9479
+ pipeableSubjectNode,
9480
+ "pipe"
9481
+ ),
9482
+ void 0,
9483
+ pipeArgs
9484
+ );
9485
+ const newNode = afterTransformations.length > 0 ? typeParser.reconstructPipingFlow({
9486
+ subject: { node: pipeNode, outType: void 0 },
9487
+ transformations: afterTransformations
9488
+ }) : pipeNode;
9489
+ changeTracker.replaceNode(sourceFile, flow2.node, newNode);
9490
+ })
9491
+ }]
9492
+ });
9493
+ break;
8643
9494
  }
9495
+ searchStartIndex = firstPipeableIndex + pipeableTransformations.length + 1;
8644
9496
  }
8645
- ts.forEachChild(node, prependNodeToVisit);
8646
9497
  }
8647
9498
  })
8648
9499
  });
@@ -9141,28 +9992,34 @@ var multipleEffectProvide = createDiagnostic({
9141
9992
  "effect",
9142
9993
  "Layer"
9143
9994
  ) || "Layer";
9144
- const parseEffectProvideLayer = (node) => {
9145
- if (ts.isCallExpression(node) && node.arguments.length > 0) {
9146
- const layer = node.arguments[0];
9147
- const type = typeCheckerUtils.getTypeAtLocation(layer);
9148
- if (!type) return void_;
9149
- return pipe(
9150
- typeParser.isNodeReferenceToEffectModuleApi("provide")(node.expression),
9151
- flatMap4(() => typeParser.layerType(type, layer)),
9152
- map8(() => ({ layer, node })),
9153
- orElse2(() => void_)
9154
- );
9155
- }
9156
- return void_;
9157
- };
9158
- const parsePipeCall = (node) => gen(function* () {
9159
- const { args: args2 } = yield* typeParser.pipeCall(node);
9995
+ const flows = yield* typeParser.pipingFlows(true)(sourceFile);
9996
+ for (const flow2 of flows) {
9160
9997
  let currentChunk = 0;
9161
9998
  const previousLayers = [[]];
9162
- for (const pipeArg of args2) {
9163
- const parsedProvide = yield* parseEffectProvideLayer(pipeArg);
9164
- if (parsedProvide) {
9165
- previousLayers[currentChunk].push(parsedProvide);
9999
+ for (const transformation of flow2.transformations) {
10000
+ if (!transformation.args || transformation.args.length === 0) {
10001
+ currentChunk++;
10002
+ previousLayers.push([]);
10003
+ continue;
10004
+ }
10005
+ const isProvideCall = yield* pipe(
10006
+ typeParser.isNodeReferenceToEffectModuleApi("provide")(transformation.callee),
10007
+ option
10008
+ );
10009
+ if (isSome2(isProvideCall)) {
10010
+ const layer = transformation.args[0];
10011
+ const type = typeCheckerUtils.getTypeAtLocation(layer);
10012
+ const node = ts.findAncestor(transformation.callee, ts.isCallExpression);
10013
+ const isLayerType = type ? yield* pipe(
10014
+ typeParser.layerType(type, layer),
10015
+ option
10016
+ ) : none2();
10017
+ if (isSome2(isLayerType) && node) {
10018
+ previousLayers[currentChunk].push({ layer, node });
10019
+ } else {
10020
+ currentChunk++;
10021
+ previousLayers.push([]);
10022
+ }
9166
10023
  } else {
9167
10024
  currentChunk++;
9168
10025
  previousLayers.push([]);
@@ -9202,19 +10059,6 @@ var multipleEffectProvide = createDiagnostic({
9202
10059
  }]
9203
10060
  });
9204
10061
  }
9205
- });
9206
- const nodeToVisit = [];
9207
- const appendNodeToVisit = (node) => {
9208
- nodeToVisit.push(node);
9209
- return void 0;
9210
- };
9211
- ts.forEachChild(sourceFile, appendNodeToVisit);
9212
- while (nodeToVisit.length > 0) {
9213
- const node = nodeToVisit.shift();
9214
- ts.forEachChild(node, appendNodeToVisit);
9215
- if (ts.isCallExpression(node)) {
9216
- yield* pipe(parsePipeCall(node), ignore);
9217
- }
9218
10062
  }
9219
10063
  })
9220
10064
  });
@@ -9495,6 +10339,140 @@ var overriddenSchemaConstructor = createDiagnostic({
9495
10339
  })
9496
10340
  });
9497
10341
 
10342
+ // src/diagnostics/preferSchemaOverJson.ts
10343
+ var preferSchemaOverJson = createDiagnostic({
10344
+ name: "preferSchemaOverJson",
10345
+ code: 44,
10346
+ description: "Suggests using Effect Schema for JSON operations instead of JSON.parse/JSON.stringify which may throw",
10347
+ severity: "suggestion",
10348
+ apply: fn("preferSchemaOverJson.apply")(function* (sourceFile, report) {
10349
+ const ts = yield* service(TypeScriptApi);
10350
+ const typeParser = yield* service(TypeParser);
10351
+ const parseJsonMethod = (node) => gen(function* () {
10352
+ if (!ts.isCallExpression(node)) return yield* fail3("node is not a call expression");
10353
+ const expression = node.expression;
10354
+ if (!ts.isPropertyAccessExpression(expression)) return yield* fail3("expression is not a property access");
10355
+ const objectExpr = expression.expression;
10356
+ const methodName = ts.idText(expression.name);
10357
+ if (!ts.isIdentifier(objectExpr) || ts.idText(objectExpr) !== "JSON") {
10358
+ return yield* fail3("object is not JSON");
10359
+ }
10360
+ if (methodName !== "parse" && methodName !== "stringify") {
10361
+ return yield* fail3("method is not parse or stringify");
10362
+ }
10363
+ return { node, methodName };
10364
+ });
10365
+ const effectTrySimple = (node) => gen(function* () {
10366
+ if (!ts.isCallExpression(node)) return yield* fail3("node is not a call expression");
10367
+ yield* typeParser.isNodeReferenceToEffectModuleApi("try")(node.expression);
10368
+ if (node.arguments.length === 0) return yield* fail3("Effect.try has no arguments");
10369
+ const lazyFn = yield* typeParser.lazyExpression(node.arguments[0]);
10370
+ const jsonMethod = yield* parseJsonMethod(lazyFn.expression);
10371
+ return { node: jsonMethod.node, methodName: jsonMethod.methodName };
10372
+ });
10373
+ const effectTryObject = (node) => gen(function* () {
10374
+ if (!ts.isCallExpression(node)) return yield* fail3("node is not a call expression");
10375
+ yield* typeParser.isNodeReferenceToEffectModuleApi("try")(node.expression);
10376
+ if (node.arguments.length === 0) return yield* fail3("Effect.try has no arguments");
10377
+ const arg = node.arguments[0];
10378
+ if (!ts.isObjectLiteralExpression(arg)) return yield* fail3("argument is not an object literal");
10379
+ const tryProp = arg.properties.find(
10380
+ (p) => ts.isPropertyAssignment(p) && ts.isIdentifier(p.name) && ts.idText(p.name) === "try"
10381
+ );
10382
+ if (!tryProp) return yield* fail3("object has no 'try' property");
10383
+ const lazyFn = yield* typeParser.lazyExpression(tryProp.initializer);
10384
+ const jsonMethod = yield* parseJsonMethod(lazyFn.expression);
10385
+ return { node: jsonMethod.node, methodName: jsonMethod.methodName };
10386
+ });
10387
+ const jsonMethodInEffectGen = (node) => gen(function* () {
10388
+ const jsonMethod = yield* parseJsonMethod(node);
10389
+ const { effectGen, scopeNode } = yield* typeParser.findEnclosingScopes(node);
10390
+ if (!effectGen || effectGen.body.statements.length === 0) {
10391
+ return yield* fail3("not inside an Effect generator");
10392
+ }
10393
+ if (scopeNode && scopeNode !== effectGen.generatorFunction) {
10394
+ return yield* fail3("inside a nested function scope");
10395
+ }
10396
+ return { node: jsonMethod.node, methodName: jsonMethod.methodName };
10397
+ });
10398
+ const nodeToVisit = [];
10399
+ const appendNodeToVisit = (node) => {
10400
+ nodeToVisit.push(node);
10401
+ return void 0;
10402
+ };
10403
+ ts.forEachChild(sourceFile, appendNodeToVisit);
10404
+ while (nodeToVisit.length > 0) {
10405
+ const node = nodeToVisit.shift();
10406
+ ts.forEachChild(node, appendNodeToVisit);
10407
+ const match3 = yield* pipe(
10408
+ firstSuccessOf([
10409
+ effectTrySimple(node),
10410
+ effectTryObject(node),
10411
+ jsonMethodInEffectGen(node)
10412
+ ]),
10413
+ option
10414
+ );
10415
+ if (isSome2(match3)) {
10416
+ report({
10417
+ location: match3.value.node,
10418
+ messageText: "Consider using Effect Schema for JSON operations instead of JSON.parse/JSON.stringify",
10419
+ fixes: []
10420
+ });
10421
+ }
10422
+ }
10423
+ })
10424
+ });
10425
+
10426
+ // src/diagnostics/redundantSchemaTagIdentifier.ts
10427
+ var redundantSchemaTagIdentifier = createDiagnostic({
10428
+ name: "redundantSchemaTagIdentifier",
10429
+ code: 42,
10430
+ description: "Suggests removing redundant identifier argument when it equals the tag value in Schema.TaggedClass/TaggedError/TaggedRequest",
10431
+ severity: "suggestion",
10432
+ apply: fn("redundantSchemaTagIdentifier.apply")(function* (sourceFile, report) {
10433
+ const ts = yield* service(TypeScriptApi);
10434
+ const typeParser = yield* service(TypeParser);
10435
+ const nodeToVisit = [];
10436
+ const appendNodeToVisit = (node) => {
10437
+ nodeToVisit.push(node);
10438
+ return void 0;
10439
+ };
10440
+ ts.forEachChild(sourceFile, appendNodeToVisit);
10441
+ while (nodeToVisit.length > 0) {
10442
+ const node = nodeToVisit.shift();
10443
+ if (ts.isClassDeclaration(node) && node.name && node.heritageClauses) {
10444
+ const result = yield* pipe(
10445
+ typeParser.extendsSchemaTaggedClass(node),
10446
+ orElse2(() => typeParser.extendsSchemaTaggedError(node)),
10447
+ orElse2(() => typeParser.extendsSchemaTaggedRequest(node)),
10448
+ orElse2(() => void_)
10449
+ );
10450
+ if (result && result.keyStringLiteral && result.tagStringLiteral) {
10451
+ const { keyStringLiteral, tagStringLiteral } = result;
10452
+ if (keyStringLiteral.text === tagStringLiteral.text) {
10453
+ report({
10454
+ location: keyStringLiteral,
10455
+ messageText: `Identifier '${keyStringLiteral.text}' is redundant since it equals the _tag value`,
10456
+ fixes: [{
10457
+ fixName: "redundantSchemaTagIdentifier_removeIdentifier",
10458
+ description: `Remove redundant identifier '${keyStringLiteral.text}'`,
10459
+ apply: gen(function* () {
10460
+ const changeTracker = yield* service(ChangeTracker);
10461
+ changeTracker.deleteRange(sourceFile, {
10462
+ pos: ts.getTokenPosOfNode(keyStringLiteral, sourceFile),
10463
+ end: keyStringLiteral.end
10464
+ });
10465
+ })
10466
+ }]
10467
+ });
10468
+ }
10469
+ }
10470
+ }
10471
+ ts.forEachChild(node, appendNodeToVisit);
10472
+ }
10473
+ })
10474
+ });
10475
+
9498
10476
  // src/diagnostics/returnEffectInGen.ts
9499
10477
  var returnEffectInGen = createDiagnostic({
9500
10478
  name: "returnEffectInGen",
@@ -9597,108 +10575,91 @@ var runEffectInsideEffect = createDiagnostic({
9597
10575
  option
9598
10576
  );
9599
10577
  if (isNone2(isEffectRunCall)) continue;
9600
- let currentParent = node.parent;
9601
- let nodeIntroduceScope = void 0;
9602
- while (currentParent) {
9603
- const possiblyEffectGen = currentParent;
9604
- if (!nodeIntroduceScope) {
9605
- if (ts.isFunctionExpression(possiblyEffectGen) || ts.isFunctionDeclaration(possiblyEffectGen) || ts.isMethodDeclaration(possiblyEffectGen) || ts.isArrowFunction(possiblyEffectGen)) {
9606
- nodeIntroduceScope = possiblyEffectGen;
9607
- continue;
9608
- }
9609
- }
9610
- const isInEffectGen = yield* pipe(
9611
- typeParser.effectGen(possiblyEffectGen),
9612
- orElse2(() => typeParser.effectFnUntracedGen(possiblyEffectGen)),
9613
- orElse2(() => typeParser.effectFnGen(possiblyEffectGen)),
9614
- option
10578
+ const { effectGen, scopeNode } = yield* typeParser.findEnclosingScopes(node);
10579
+ if (effectGen && effectGen.body.statements.length > 0) {
10580
+ const nodeText = sourceFile.text.substring(
10581
+ ts.getTokenPosOfNode(node.expression, sourceFile),
10582
+ node.expression.end
9615
10583
  );
9616
- if (isSome2(isInEffectGen) && isInEffectGen.value.body.statements.length > 0) {
9617
- const nodeText = sourceFile.text.substring(
9618
- ts.getTokenPosOfNode(node.expression, sourceFile),
9619
- node.expression.end
9620
- );
9621
- if (nodeIntroduceScope && nodeIntroduceScope !== isInEffectGen.value.generatorFunction) {
9622
- const fixAddRuntime = gen(function* () {
9623
- const changeTracker = yield* service(ChangeTracker);
9624
- const runtimeModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, "effect", "Runtime") || "Runtime";
9625
- const effectModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, "effect", "Effect") || "Effect";
9626
- let runtimeIdentifier = void 0;
9627
- for (const statement of isInEffectGen.value.generatorFunction.body.statements) {
9628
- if (ts.isVariableStatement(statement) && statement.declarationList.declarations.length === 1) {
9629
- const declaration = statement.declarationList.declarations[0];
9630
- if (declaration.initializer && ts.isYieldExpression(declaration.initializer) && declaration.initializer.asteriskToken && declaration.initializer.expression) {
9631
- const yieldedExpression = declaration.initializer.expression;
9632
- if (ts.isCallExpression(yieldedExpression)) {
9633
- const maybeEffectRuntime = yield* pipe(
9634
- typeParser.isNodeReferenceToEffectModuleApi("runtime")(yieldedExpression.expression),
9635
- option
9636
- );
9637
- if (isSome2(maybeEffectRuntime) && ts.isIdentifier(declaration.name)) {
9638
- runtimeIdentifier = ts.idText(declaration.name);
9639
- }
10584
+ if (scopeNode && scopeNode !== effectGen.generatorFunction) {
10585
+ const fixAddRuntime = gen(function* () {
10586
+ const changeTracker = yield* service(ChangeTracker);
10587
+ const runtimeModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, "effect", "Runtime") || "Runtime";
10588
+ const effectModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, "effect", "Effect") || "Effect";
10589
+ let runtimeIdentifier = void 0;
10590
+ for (const statement of effectGen.generatorFunction.body.statements) {
10591
+ if (ts.isVariableStatement(statement) && statement.declarationList.declarations.length === 1) {
10592
+ const declaration = statement.declarationList.declarations[0];
10593
+ if (declaration.initializer && ts.isYieldExpression(declaration.initializer) && declaration.initializer.asteriskToken && declaration.initializer.expression) {
10594
+ const yieldedExpression = declaration.initializer.expression;
10595
+ if (ts.isCallExpression(yieldedExpression)) {
10596
+ const maybeEffectRuntime = yield* pipe(
10597
+ typeParser.isNodeReferenceToEffectModuleApi("runtime")(yieldedExpression.expression),
10598
+ option
10599
+ );
10600
+ if (isSome2(maybeEffectRuntime) && ts.isIdentifier(declaration.name)) {
10601
+ runtimeIdentifier = ts.idText(declaration.name);
9640
10602
  }
9641
10603
  }
9642
10604
  }
9643
10605
  }
9644
- if (!runtimeIdentifier) {
9645
- changeTracker.insertNodeAt(
9646
- sourceFile,
9647
- isInEffectGen.value.body.statements[0].pos,
9648
- ts.factory.createVariableStatement(
10606
+ }
10607
+ if (!runtimeIdentifier) {
10608
+ changeTracker.insertNodeAt(
10609
+ sourceFile,
10610
+ effectGen.body.statements[0].pos,
10611
+ ts.factory.createVariableStatement(
10612
+ void 0,
10613
+ ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(
10614
+ "effectRuntime",
9649
10615
  void 0,
9650
- ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(
9651
- "effectRuntime",
9652
- void 0,
9653
- void 0,
9654
- ts.factory.createYieldExpression(
9655
- ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
9656
- ts.factory.createCallExpression(
9657
- ts.factory.createPropertyAccessExpression(
9658
- ts.factory.createIdentifier(effectModuleIdentifier),
9659
- "runtime"
9660
- ),
9661
- [ts.factory.createTypeReferenceNode("never")],
9662
- []
9663
- )
10616
+ void 0,
10617
+ ts.factory.createYieldExpression(
10618
+ ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
10619
+ ts.factory.createCallExpression(
10620
+ ts.factory.createPropertyAccessExpression(
10621
+ ts.factory.createIdentifier(effectModuleIdentifier),
10622
+ "runtime"
10623
+ ),
10624
+ [ts.factory.createTypeReferenceNode("never")],
10625
+ []
9664
10626
  )
9665
- )], ts.NodeFlags.Const)
9666
- ),
9667
- {
9668
- prefix: "\n",
9669
- suffix: "\n"
9670
- }
9671
- );
9672
- }
9673
- changeTracker.deleteRange(sourceFile, {
9674
- pos: ts.getTokenPosOfNode(node.expression, sourceFile),
9675
- end: node.arguments[0].pos
9676
- });
9677
- changeTracker.insertText(
9678
- sourceFile,
9679
- node.arguments[0].pos,
9680
- `${runtimeModuleIdentifier}.${isEffectRunCall.value.methodName}(${runtimeIdentifier || "effectRuntime"}, `
10627
+ )
10628
+ )], ts.NodeFlags.Const)
10629
+ ),
10630
+ {
10631
+ prefix: "\n",
10632
+ suffix: "\n"
10633
+ }
9681
10634
  );
10635
+ }
10636
+ changeTracker.deleteRange(sourceFile, {
10637
+ pos: ts.getTokenPosOfNode(node.expression, sourceFile),
10638
+ end: node.arguments[0].pos
9682
10639
  });
9683
- report({
9684
- location: node.expression,
9685
- messageText: `Using ${nodeText} inside an Effect is not recommended. The same runtime should generally be used instead to run child effects.
10640
+ changeTracker.insertText(
10641
+ sourceFile,
10642
+ node.arguments[0].pos,
10643
+ `${runtimeModuleIdentifier}.${isEffectRunCall.value.methodName}(${runtimeIdentifier || "effectRuntime"}, `
10644
+ );
10645
+ });
10646
+ report({
10647
+ location: node.expression,
10648
+ messageText: `Using ${nodeText} inside an Effect is not recommended. The same runtime should generally be used instead to run child effects.
9686
10649
  Consider extracting the Runtime by using for example Effect.runtime and then use Runtime.${isEffectRunCall.value.methodName} with the extracted runtime instead.`,
9687
- fixes: [{
9688
- fixName: "runEffectInsideEffect_fix",
9689
- description: "Use a runtime to run the Effect",
9690
- apply: fixAddRuntime
9691
- }]
9692
- });
9693
- } else {
9694
- report({
9695
- location: node.expression,
9696
- messageText: `Using ${nodeText} inside an Effect is not recommended. Effects inside generators can usually just be yielded.`,
9697
- fixes: []
9698
- });
9699
- }
10650
+ fixes: [{
10651
+ fixName: "runEffectInsideEffect_fix",
10652
+ description: "Use a runtime to run the Effect",
10653
+ apply: fixAddRuntime
10654
+ }]
10655
+ });
10656
+ } else {
10657
+ report({
10658
+ location: node.expression,
10659
+ messageText: `Using ${nodeText} inside an Effect is not recommended. Effects inside generators can usually just be yielded.`,
10660
+ fixes: []
10661
+ });
9700
10662
  }
9701
- currentParent = currentParent.parent;
9702
10663
  }
9703
10664
  }
9704
10665
  })
@@ -9784,6 +10745,59 @@ var schemaStructWithTag = createDiagnostic({
9784
10745
  })
9785
10746
  });
9786
10747
 
10748
+ // src/diagnostics/schemaSyncInEffect.ts
10749
+ var syncToEffectMethod = {
10750
+ decodeSync: "decode",
10751
+ decodeUnknownSync: "decodeUnknown",
10752
+ encodeSync: "encode",
10753
+ encodeUnknownSync: "encodeUnknown"
10754
+ };
10755
+ var schemaSyncInEffect = createDiagnostic({
10756
+ name: "schemaSyncInEffect",
10757
+ code: 43,
10758
+ description: "Suggests using Effect-based Schema methods instead of sync methods inside Effect generators",
10759
+ severity: "suggestion",
10760
+ apply: fn("schemaSyncInEffect.apply")(function* (sourceFile, report) {
10761
+ const ts = yield* service(TypeScriptApi);
10762
+ const typeParser = yield* service(TypeParser);
10763
+ const parseSchemaSyncMethod = (node, methodName) => pipe(
10764
+ typeParser.isNodeReferenceToEffectParseResultModuleApi(methodName)(node),
10765
+ map8(() => ({ node, methodName }))
10766
+ );
10767
+ const nodeToVisit = [];
10768
+ const appendNodeToVisit = (node) => {
10769
+ nodeToVisit.push(node);
10770
+ return void 0;
10771
+ };
10772
+ ts.forEachChild(sourceFile, appendNodeToVisit);
10773
+ while (nodeToVisit.length > 0) {
10774
+ const node = nodeToVisit.shift();
10775
+ ts.forEachChild(node, appendNodeToVisit);
10776
+ if (!ts.isCallExpression(node)) continue;
10777
+ const isSchemaSyncCall = yield* pipe(
10778
+ firstSuccessOf(
10779
+ Object.keys(syncToEffectMethod).map((methodName) => parseSchemaSyncMethod(node.expression, methodName))
10780
+ ),
10781
+ option
10782
+ );
10783
+ if (isNone2(isSchemaSyncCall)) continue;
10784
+ const { effectGen, scopeNode } = yield* typeParser.findEnclosingScopes(node);
10785
+ if (!effectGen || effectGen.body.statements.length === 0) continue;
10786
+ if (scopeNode && scopeNode !== effectGen.generatorFunction) continue;
10787
+ const nodeText = sourceFile.text.substring(
10788
+ ts.getTokenPosOfNode(node.expression, sourceFile),
10789
+ node.expression.end
10790
+ );
10791
+ const effectMethodName = syncToEffectMethod[isSchemaSyncCall.value.methodName];
10792
+ report({
10793
+ location: node.expression,
10794
+ messageText: `Using ${nodeText} inside an Effect generator is not recommended. Use Schema.${effectMethodName} instead to get properly typed ParseError in the error channel.`,
10795
+ fixes: []
10796
+ });
10797
+ }
10798
+ })
10799
+ });
10800
+
9787
10801
  // src/diagnostics/schemaUnionOfLiterals.ts
9788
10802
  var schemaUnionOfLiterals = createDiagnostic({
9789
10803
  name: "schemaUnionOfLiterals",
@@ -10495,7 +11509,12 @@ var diagnostics = [
10495
11509
  schemaStructWithTag,
10496
11510
  globalErrorInEffectCatch,
10497
11511
  globalErrorInEffectFailure,
10498
- layerMergeAllWithDependencies
11512
+ layerMergeAllWithDependencies,
11513
+ effectMapVoid,
11514
+ effectFnOpportunity,
11515
+ redundantSchemaTagIdentifier,
11516
+ schemaSyncInEffect,
11517
+ preferSchemaOverJson
10499
11518
  ];
10500
11519
 
10501
11520
  // src/completions/effectDiagnosticsComment.ts
@@ -10600,7 +11619,7 @@ var effectSchemaSelfInClasses = createCompletion({
10600
11619
  completions2.push({
10601
11620
  name: `TaggedError<${name}>`,
10602
11621
  kind: ts.ScriptElementKind.constElement,
10603
- insertText: isFullyQualified ? `${schemaIdentifier}.TaggedError<${name}>("${errorTagKey}")("${errorTagKey}", {${"${0}"}}){}` : `TaggedError<${name}>("${errorTagKey}")("${errorTagKey}", {${"${0}"}}){}`,
11622
+ insertText: isFullyQualified ? `${schemaIdentifier}.TaggedError<${name}>()("${errorTagKey}", {${"${0}"}}){}` : `TaggedError<${name}>()("${errorTagKey}", {${"${0}"}}){}`,
10604
11623
  replacementSpan,
10605
11624
  isSnippet: true
10606
11625
  });
@@ -10615,7 +11634,7 @@ var effectSchemaSelfInClasses = createCompletion({
10615
11634
  completions2.push({
10616
11635
  name: `TaggedClass<${name}>`,
10617
11636
  kind: ts.ScriptElementKind.constElement,
10618
- insertText: isFullyQualified ? `${schemaIdentifier}.TaggedClass<${name}>("${name}")("${name}", {${"${0}"}}){}` : `TaggedClass<${name}>("${name}")("${name}", {${"${0}"}}){}`,
11637
+ insertText: isFullyQualified ? `${schemaIdentifier}.TaggedClass<${name}>()("${name}", {${"${0}"}}){}` : `TaggedClass<${name}>()("${name}", {${"${0}"}}){}`,
10619
11638
  replacementSpan,
10620
11639
  isSnippet: true
10621
11640
  });
@@ -10630,7 +11649,7 @@ var effectSchemaSelfInClasses = createCompletion({
10630
11649
  completions2.push({
10631
11650
  name: `TaggedRequest<${name}>`,
10632
11651
  kind: ts.ScriptElementKind.constElement,
10633
- insertText: isFullyQualified ? `${schemaIdentifier}.TaggedRequest<${name}>("${name}")("${name}", {${"${0}"}}){}` : `TaggedRequest<${name}>("${name}")("${name}", {${"${0}"}}){}`,
11652
+ insertText: isFullyQualified ? `${schemaIdentifier}.TaggedRequest<${name}>()("${name}", {${"${0}"}}){}` : `TaggedRequest<${name}>()("${name}", {${"${0}"}}){}`,
10634
11653
  replacementSpan,
10635
11654
  isSnippet: true
10636
11655
  });
@@ -16382,6 +17401,23 @@ var extractOutlineGraph = fn("extractOutlineGraph")(function* (layerGraph) {
16382
17401
  }
16383
17402
  return endMutation2(mutableGraph);
16384
17403
  });
17404
+ var collectOutlineGraphActualProvides = fn("collectOutlineGraphActualProvides")(
17405
+ function* (outlineGraph) {
17406
+ const typeCheckerUtils = yield* service(TypeCheckerUtils);
17407
+ const seenTypes = /* @__PURE__ */ new Set();
17408
+ const result = [];
17409
+ for (const nodeInfo of values2(nodes(outlineGraph))) {
17410
+ for (const actualProvide of nodeInfo.actualProvides) {
17411
+ if (!seenTypes.has(actualProvide)) {
17412
+ seenTypes.add(actualProvide);
17413
+ result.push(actualProvide);
17414
+ }
17415
+ }
17416
+ }
17417
+ result.sort(typeCheckerUtils.deterministicTypeOrder);
17418
+ return result;
17419
+ }
17420
+ );
16385
17421
  var formatLayerOutlineGraph = fn("formatLayerOutlineGraph")(
16386
17422
  function* (layerOutlineGraph, fromSourceFile) {
16387
17423
  const tsUtils = yield* service(TypeScriptUtils);
@@ -16448,11 +17484,12 @@ var dfsPostOrderWithOrder = (graph, config) => {
16448
17484
  }));
16449
17485
  };
16450
17486
  var convertOutlineGraphToLayerMagic = fn("convertOutlineGraphToLayerMagic")(
16451
- function* (outlineGraph, targetOutput) {
17487
+ function* (outlineGraph, targetOutputs) {
16452
17488
  const typeCheckerUtils = yield* service(TypeCheckerUtils);
16453
17489
  const ts = yield* service(TypeScriptApi);
16454
17490
  const result = [];
16455
- const missingOutputTypes = new Set(typeCheckerUtils.unrollUnionMembers(targetOutput));
17491
+ const outputTypes = flatten(map4(targetOutputs, (_) => typeCheckerUtils.unrollUnionMembers(_)));
17492
+ const missingOutputTypes = new Set(outputTypes);
16456
17493
  const currentRequiredTypes = /* @__PURE__ */ new Set();
16457
17494
  const orderByProvidedCount = mapInput(
16458
17495
  reverse(number2),
@@ -17361,7 +18398,7 @@ var layerMagic = createRefactor({
17361
18398
  const { layerMagicNodes, missingOutputTypes } = yield* pipe(
17362
18399
  convertOutlineGraphToLayerMagic(
17363
18400
  extractedLayers,
17364
- _targetLayer.ROut
18401
+ [_targetLayer.ROut]
17365
18402
  ),
17366
18403
  provideService(TypeCheckerApi, typeChecker),
17367
18404
  provideService(TypeCheckerUtils, typeCheckerUtils),