@effect/language-service 0.62.5 → 0.63.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/README.md +5 -1
- package/cli.js +2761 -675
- package/cli.js.map +1 -1
- package/effect-lsp-patch-utils.js +342 -147
- package/effect-lsp-patch-utils.js.map +1 -1
- package/index.js +459 -203
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +342 -147
- package/transform.js.map +1 -1
|
@@ -26,7 +26,7 @@ __export(effect_lsp_patch_utils_exports, {
|
|
|
26
26
|
});
|
|
27
27
|
module.exports = __toCommonJS(effect_lsp_patch_utils_exports);
|
|
28
28
|
|
|
29
|
-
// node_modules/.pnpm/effect@3.19.
|
|
29
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Function.js
|
|
30
30
|
var isFunction = (input) => typeof input === "function";
|
|
31
31
|
var dual = function(arity, body) {
|
|
32
32
|
if (typeof arity === "function") {
|
|
@@ -122,7 +122,7 @@ function pipe(a, ab, bc, cd, de, ef, fg, gh, hi) {
|
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
// node_modules/.pnpm/effect@3.19.
|
|
125
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/GlobalValue.js
|
|
126
126
|
var globalStoreId = `effect/GlobalValue`;
|
|
127
127
|
var globalStore;
|
|
128
128
|
var globalValue = (id, compute) => {
|
|
@@ -136,7 +136,7 @@ var globalValue = (id, compute) => {
|
|
|
136
136
|
return globalStore.get(id);
|
|
137
137
|
};
|
|
138
138
|
|
|
139
|
-
// node_modules/.pnpm/effect@3.19.
|
|
139
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Predicate.js
|
|
140
140
|
var isString = (input) => typeof input === "string";
|
|
141
141
|
var isNumber = (input) => typeof input === "number";
|
|
142
142
|
var isBoolean = (input) => typeof input === "boolean";
|
|
@@ -146,7 +146,7 @@ var isObject = (input) => isRecordOrArray(input) || isFunction2(input);
|
|
|
146
146
|
var hasProperty = /* @__PURE__ */ dual(2, (self, property) => isObject(self) && property in self);
|
|
147
147
|
var isRecord = (input) => isRecordOrArray(input) && !Array.isArray(input);
|
|
148
148
|
|
|
149
|
-
// node_modules/.pnpm/effect@3.19.
|
|
149
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Utils.js
|
|
150
150
|
var GenKindTypeId = /* @__PURE__ */ Symbol.for("effect/Gen/GenKind");
|
|
151
151
|
var GenKindImpl = class {
|
|
152
152
|
value;
|
|
@@ -268,7 +268,7 @@ var internalCall = isNotOptimizedAway ? standard.effect_internal_function : forc
|
|
|
268
268
|
var genConstructor = function* () {
|
|
269
269
|
}.constructor;
|
|
270
270
|
|
|
271
|
-
// node_modules/.pnpm/effect@3.19.
|
|
271
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Hash.js
|
|
272
272
|
var randomHashCache = /* @__PURE__ */ globalValue(/* @__PURE__ */ Symbol.for("effect/Hash/randomHashCache"), () => /* @__PURE__ */ new WeakMap());
|
|
273
273
|
var symbol = /* @__PURE__ */ Symbol.for("effect/Hash");
|
|
274
274
|
var hash = (self) => {
|
|
@@ -293,6 +293,9 @@ var hash = (self) => {
|
|
|
293
293
|
if (self === null) {
|
|
294
294
|
return string("null");
|
|
295
295
|
} else if (self instanceof Date) {
|
|
296
|
+
if (Number.isNaN(self.getTime())) {
|
|
297
|
+
return string("Invalid Date");
|
|
298
|
+
}
|
|
296
299
|
return hash(self.toISOString());
|
|
297
300
|
} else if (self instanceof URL) {
|
|
298
301
|
return hash(self.href);
|
|
@@ -367,7 +370,7 @@ var cached = function() {
|
|
|
367
370
|
return hash2;
|
|
368
371
|
};
|
|
369
372
|
|
|
370
|
-
// node_modules/.pnpm/effect@3.19.
|
|
373
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Equal.js
|
|
371
374
|
var symbol2 = /* @__PURE__ */ Symbol.for("effect/Equal");
|
|
372
375
|
function equals() {
|
|
373
376
|
if (arguments.length === 1) {
|
|
@@ -392,7 +395,9 @@ function compareBoth(self, that) {
|
|
|
392
395
|
return structuralRegionState.enabled && structuralRegionState.tester ? structuralRegionState.tester(self, that) : false;
|
|
393
396
|
}
|
|
394
397
|
} else if (self instanceof Date && that instanceof Date) {
|
|
395
|
-
|
|
398
|
+
const t1 = self.getTime();
|
|
399
|
+
const t2 = that.getTime();
|
|
400
|
+
return t1 === t2 || Number.isNaN(t1) && Number.isNaN(t2);
|
|
396
401
|
} else if (self instanceof URL && that instanceof URL) {
|
|
397
402
|
return self.href === that.href;
|
|
398
403
|
}
|
|
@@ -421,7 +426,7 @@ function compareBoth(self, that) {
|
|
|
421
426
|
var isEqual = (u) => hasProperty(u, symbol2);
|
|
422
427
|
var equivalence = () => equals;
|
|
423
428
|
|
|
424
|
-
// node_modules/.pnpm/effect@3.19.
|
|
429
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Inspectable.js
|
|
425
430
|
var NodeInspectSymbol = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
|
|
426
431
|
var toJSON = (x) => {
|
|
427
432
|
try {
|
|
@@ -473,7 +478,7 @@ var redact = (u) => {
|
|
|
473
478
|
return u;
|
|
474
479
|
};
|
|
475
480
|
|
|
476
|
-
// node_modules/.pnpm/effect@3.19.
|
|
481
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Pipeable.js
|
|
477
482
|
var pipeArguments = (self, args2) => {
|
|
478
483
|
switch (args2.length) {
|
|
479
484
|
case 0:
|
|
@@ -506,14 +511,14 @@ var pipeArguments = (self, args2) => {
|
|
|
506
511
|
}
|
|
507
512
|
};
|
|
508
513
|
|
|
509
|
-
// node_modules/.pnpm/effect@3.19.
|
|
514
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/opCodes/effect.js
|
|
510
515
|
var OP_COMMIT = "Commit";
|
|
511
516
|
|
|
512
|
-
// node_modules/.pnpm/effect@3.19.
|
|
513
|
-
var moduleVersion = "3.19.
|
|
517
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/version.js
|
|
518
|
+
var moduleVersion = "3.19.13";
|
|
514
519
|
var getCurrentVersion = () => moduleVersion;
|
|
515
520
|
|
|
516
|
-
// node_modules/.pnpm/effect@3.19.
|
|
521
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/effectable.js
|
|
517
522
|
var EffectTypeId = /* @__PURE__ */ Symbol.for("effect/Effect");
|
|
518
523
|
var StreamTypeId = /* @__PURE__ */ Symbol.for("effect/Stream");
|
|
519
524
|
var SinkTypeId = /* @__PURE__ */ Symbol.for("effect/Sink");
|
|
@@ -600,7 +605,7 @@ var StructuralCommitPrototype = {
|
|
|
600
605
|
...StructuralPrototype
|
|
601
606
|
};
|
|
602
607
|
|
|
603
|
-
// node_modules/.pnpm/effect@3.19.
|
|
608
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/option.js
|
|
604
609
|
var TypeId = /* @__PURE__ */ Symbol.for("effect/Option");
|
|
605
610
|
var CommonProto = {
|
|
606
611
|
...EffectPrototype,
|
|
@@ -658,7 +663,7 @@ var some = (value) => {
|
|
|
658
663
|
return a;
|
|
659
664
|
};
|
|
660
665
|
|
|
661
|
-
// node_modules/.pnpm/effect@3.19.
|
|
666
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/either.js
|
|
662
667
|
var TypeId2 = /* @__PURE__ */ Symbol.for("effect/Either");
|
|
663
668
|
var CommonProto2 = {
|
|
664
669
|
...EffectPrototype,
|
|
@@ -720,7 +725,7 @@ var right = (right3) => {
|
|
|
720
725
|
return a;
|
|
721
726
|
};
|
|
722
727
|
|
|
723
|
-
// node_modules/.pnpm/effect@3.19.
|
|
728
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Either.js
|
|
724
729
|
var right2 = right;
|
|
725
730
|
var left2 = left;
|
|
726
731
|
var isLeft2 = isLeft;
|
|
@@ -728,14 +733,14 @@ var isRight2 = isRight;
|
|
|
728
733
|
var map = /* @__PURE__ */ dual(2, (self, f) => isRight2(self) ? right2(f(self.right)) : left2(self.left));
|
|
729
734
|
var getOrElse = /* @__PURE__ */ dual(2, (self, onLeft) => isLeft2(self) ? onLeft(self.left) : self.right);
|
|
730
735
|
|
|
731
|
-
// node_modules/.pnpm/effect@3.19.
|
|
736
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/array.js
|
|
732
737
|
var isNonEmptyArray = (self) => self.length > 0;
|
|
733
738
|
|
|
734
|
-
// node_modules/.pnpm/effect@3.19.
|
|
739
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Order.js
|
|
735
740
|
var make = (compare) => (self, that) => self === that ? 0 : compare(self, that);
|
|
736
741
|
var string2 = /* @__PURE__ */ make((self, that) => self < that ? -1 : 1);
|
|
737
742
|
|
|
738
|
-
// node_modules/.pnpm/effect@3.19.
|
|
743
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Option.js
|
|
739
744
|
var none2 = () => none;
|
|
740
745
|
var some2 = some;
|
|
741
746
|
var isNone2 = isNone;
|
|
@@ -745,7 +750,7 @@ var orElse = /* @__PURE__ */ dual(2, (self, that) => isNone2(self) ? that() : se
|
|
|
745
750
|
var fromNullable = (nullableValue) => nullableValue == null ? none2() : some2(nullableValue);
|
|
746
751
|
var getOrUndefined = /* @__PURE__ */ getOrElse2(constUndefined);
|
|
747
752
|
|
|
748
|
-
// node_modules/.pnpm/effect@3.19.
|
|
753
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Record.js
|
|
749
754
|
var map2 = /* @__PURE__ */ dual(2, (self, f) => {
|
|
750
755
|
const out = {
|
|
751
756
|
...self
|
|
@@ -757,7 +762,7 @@ var map2 = /* @__PURE__ */ dual(2, (self, f) => {
|
|
|
757
762
|
});
|
|
758
763
|
var keys = (self) => Object.keys(self);
|
|
759
764
|
|
|
760
|
-
// node_modules/.pnpm/effect@3.19.
|
|
765
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Array.js
|
|
761
766
|
var fromIterable = (collection) => Array.isArray(collection) ? collection : Array.from(collection);
|
|
762
767
|
var append = /* @__PURE__ */ dual(2, (self, last) => [...self, last]);
|
|
763
768
|
var appendAll = /* @__PURE__ */ dual(2, (self, that) => fromIterable(self).concat(fromIterable(that)));
|
|
@@ -797,7 +802,10 @@ var containsWith = (isEquivalent) => dual(2, (self, a) => {
|
|
|
797
802
|
var _equivalence = /* @__PURE__ */ equivalence();
|
|
798
803
|
var intersectionWith = (isEquivalent) => {
|
|
799
804
|
const has = containsWith(isEquivalent);
|
|
800
|
-
return dual(2, (self, that) =>
|
|
805
|
+
return dual(2, (self, that) => {
|
|
806
|
+
const bs = fromIterable(that);
|
|
807
|
+
return fromIterable(self).filter((a) => has(bs, a));
|
|
808
|
+
});
|
|
801
809
|
};
|
|
802
810
|
var intersection = /* @__PURE__ */ intersectionWith(_equivalence);
|
|
803
811
|
var empty = () => [];
|
|
@@ -875,12 +883,12 @@ var SingleShotGen2 = class _SingleShotGen {
|
|
|
875
883
|
return new _SingleShotGen(this.self);
|
|
876
884
|
}
|
|
877
885
|
};
|
|
878
|
-
var evaluate = Symbol.for("Nano.evaluate");
|
|
879
|
-
var contA = Symbol.for("Nano.contA");
|
|
880
|
-
var contE = Symbol.for("Nano.contE");
|
|
881
|
-
var contAll = Symbol.for("Nano.contAll");
|
|
882
|
-
var NanoYield = Symbol.for("Nano.yield");
|
|
883
|
-
var args = Symbol.for("Nano.args");
|
|
886
|
+
var evaluate = /* @__PURE__ */ Symbol.for("Nano.evaluate");
|
|
887
|
+
var contA = /* @__PURE__ */ Symbol.for("Nano.contA");
|
|
888
|
+
var contE = /* @__PURE__ */ Symbol.for("Nano.contE");
|
|
889
|
+
var contAll = /* @__PURE__ */ Symbol.for("Nano.contAll");
|
|
890
|
+
var NanoYield = /* @__PURE__ */ Symbol.for("Nano.yield");
|
|
891
|
+
var args = /* @__PURE__ */ Symbol.for("Nano.args");
|
|
884
892
|
var NanoDefectException = class {
|
|
885
893
|
constructor(message, lastSpan) {
|
|
886
894
|
this.message = message;
|
|
@@ -2193,6 +2201,8 @@ var nanoLayer2 = (fa) => pipe(
|
|
|
2193
2201
|
function makeTypeCheckerUtils(ts, typeChecker, tsUtils) {
|
|
2194
2202
|
const readonlyArraySymbol = typeChecker.resolveName("ReadonlyArray", void 0, ts.SymbolFlags.Type, false);
|
|
2195
2203
|
const globalReadonlyArrayType = readonlyArraySymbol ? typeChecker.getDeclaredTypeOfSymbol(readonlyArraySymbol) : void 0;
|
|
2204
|
+
const errorSymbol = typeChecker.resolveName("Error", void 0, ts.SymbolFlags.Type, false);
|
|
2205
|
+
const globalErrorType = errorSymbol ? typeChecker.getDeclaredTypeOfSymbol(errorSymbol) : void 0;
|
|
2196
2206
|
function isUnion(type) {
|
|
2197
2207
|
return !!(type.flags & ts.TypeFlags.Union);
|
|
2198
2208
|
}
|
|
@@ -2441,6 +2451,10 @@ function makeTypeCheckerUtils(ts, typeChecker, tsUtils) {
|
|
|
2441
2451
|
function typeToSimplifiedTypeNode(type, enclosingNode, flags) {
|
|
2442
2452
|
return typeToSimplifiedTypeNodeWorker(type, enclosingNode, flags, 0);
|
|
2443
2453
|
}
|
|
2454
|
+
function isGlobalErrorType(type) {
|
|
2455
|
+
if (!globalErrorType) return false;
|
|
2456
|
+
return typeChecker.isTypeAssignableTo(type, globalErrorType) && typeChecker.isTypeAssignableTo(globalErrorType, type);
|
|
2457
|
+
}
|
|
2444
2458
|
function typeToSimplifiedTypeNodeWorker(type, enclosingNode, flags, depth) {
|
|
2445
2459
|
const fallbackStandard = () => {
|
|
2446
2460
|
const typeNode = typeChecker.typeToTypeNode(type, enclosingNode, flags);
|
|
@@ -2510,6 +2524,15 @@ function makeTypeCheckerUtils(ts, typeChecker, tsUtils) {
|
|
|
2510
2524
|
}
|
|
2511
2525
|
return fallbackStandard();
|
|
2512
2526
|
}
|
|
2527
|
+
function getTypeAtLocation(node) {
|
|
2528
|
+
if (node.parent && ts.isJsxSelfClosingElement(node.parent) && node.parent.tagName === node) return;
|
|
2529
|
+
if (node.parent && ts.isJsxOpeningElement(node.parent) && node.parent.tagName === node) return;
|
|
2530
|
+
if (node.parent && ts.isJsxClosingElement(node.parent) && node.parent.tagName === node) return;
|
|
2531
|
+
if (node.parent && ts.isJsxAttribute(node.parent) && node.parent.name === node) return;
|
|
2532
|
+
if (ts.isExpression(node) || ts.isTypeNode(node)) {
|
|
2533
|
+
return typeChecker.getTypeAtLocation(node);
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2513
2536
|
return {
|
|
2514
2537
|
isUnion,
|
|
2515
2538
|
isReadonlyArrayType,
|
|
@@ -2521,7 +2544,9 @@ function makeTypeCheckerUtils(ts, typeChecker, tsUtils) {
|
|
|
2521
2544
|
deterministicTypeOrder,
|
|
2522
2545
|
getInferredReturnType,
|
|
2523
2546
|
expectedAndRealType,
|
|
2524
|
-
typeToSimplifiedTypeNode
|
|
2547
|
+
typeToSimplifiedTypeNode,
|
|
2548
|
+
isGlobalErrorType,
|
|
2549
|
+
getTypeAtLocation
|
|
2525
2550
|
};
|
|
2526
2551
|
}
|
|
2527
2552
|
|
|
@@ -2643,7 +2668,7 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
2643
2668
|
return isSymbolExportOfPackageModule(symbol3, packageName, memberName, isCorrectSourceFile);
|
|
2644
2669
|
};
|
|
2645
2670
|
const findSymbolsMatchingPackageAndExportedName = (packageName, exportedSymbolName) => cachedBy(
|
|
2646
|
-
fn("TypeParser.findSymbolsMatchingPackageAndExportedName")(function* (
|
|
2671
|
+
fn("TypeParser.findSymbolsMatchingPackageAndExportedName")(function* () {
|
|
2647
2672
|
const result = [];
|
|
2648
2673
|
for (const sourceFile of program.getSourceFiles()) {
|
|
2649
2674
|
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
|
@@ -2657,7 +2682,7 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
2657
2682
|
return result;
|
|
2658
2683
|
}),
|
|
2659
2684
|
`TypeParser.findSymbolsMatchingPackageAndExportedName(${packageName}, ${exportedSymbolName})`,
|
|
2660
|
-
(
|
|
2685
|
+
() => program
|
|
2661
2686
|
);
|
|
2662
2687
|
const isCauseTypeSourceFile = cachedBy(
|
|
2663
2688
|
fn("TypeParser.isCauseTypeSourceFile")(function* (sourceFile) {
|
|
@@ -2672,20 +2697,22 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
2672
2697
|
"TypeParser.isCauseTypeSourceFile",
|
|
2673
2698
|
(sourceFile) => sourceFile
|
|
2674
2699
|
);
|
|
2675
|
-
const
|
|
2676
|
-
fn("TypeParser.
|
|
2677
|
-
const symbols = yield* findSymbolsMatchingPackageAndExportedName("effect", "YieldableError")(
|
|
2678
|
-
const result = [];
|
|
2700
|
+
const extendsCauseYieldableError = cachedBy(
|
|
2701
|
+
fn("TypeParser.extendsCauseYieldableError")(function* (givenType) {
|
|
2702
|
+
const symbols = yield* findSymbolsMatchingPackageAndExportedName("effect", "YieldableError")();
|
|
2679
2703
|
for (const [symbol3, sourceFile] of symbols) {
|
|
2680
|
-
const causeFile = yield* isCauseTypeSourceFile(sourceFile);
|
|
2704
|
+
const causeFile = yield* pipe(isCauseTypeSourceFile(sourceFile), orElse2(() => void_));
|
|
2681
2705
|
if (!causeFile) continue;
|
|
2682
2706
|
const type = typeChecker.getDeclaredTypeOfSymbol(symbol3);
|
|
2683
|
-
|
|
2707
|
+
if (!type) continue;
|
|
2708
|
+
if (typeChecker.isTypeAssignableTo(givenType, type)) {
|
|
2709
|
+
return type;
|
|
2710
|
+
}
|
|
2684
2711
|
}
|
|
2685
|
-
return
|
|
2712
|
+
return yield* typeParserIssue("Type does not extend Cause.YieldableError", givenType);
|
|
2686
2713
|
}),
|
|
2687
|
-
"TypeParser.
|
|
2688
|
-
(
|
|
2714
|
+
"TypeParser.extendsCauseYieldableError",
|
|
2715
|
+
(type) => type
|
|
2689
2716
|
);
|
|
2690
2717
|
function covariantTypeArgument(type) {
|
|
2691
2718
|
const signatures = typeChecker.getSignaturesOfType(type, ts.SignatureKind.Call);
|
|
@@ -3075,7 +3102,8 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
3075
3102
|
}
|
|
3076
3103
|
if (ts.isYieldExpression(nodeToCheck) && nodeToCheck.asteriskToken && nodeToCheck.expression) {
|
|
3077
3104
|
const yieldedExpression = nodeToCheck.expression;
|
|
3078
|
-
const type =
|
|
3105
|
+
const type = typeCheckerUtils.getTypeAtLocation(yieldedExpression);
|
|
3106
|
+
if (!type) continue;
|
|
3079
3107
|
const { A: successType } = yield* effectType(type, yieldedExpression);
|
|
3080
3108
|
let replacementNode = succeed(yieldedExpression);
|
|
3081
3109
|
if (!explicitReturn && !(successType.flags & ts.TypeFlags.VoidLike)) {
|
|
@@ -3666,11 +3694,79 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
3666
3694
|
"TypeParser.extendsEffectService",
|
|
3667
3695
|
(atLocation) => atLocation
|
|
3668
3696
|
);
|
|
3697
|
+
const isEffectSqlModelTypeSourceFile = cachedBy(
|
|
3698
|
+
fn("TypeParser.isEffectSqlModelTypeSourceFile")(function* (sourceFile) {
|
|
3699
|
+
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
|
3700
|
+
if (!moduleSymbol) return yield* typeParserIssue("Node has no symbol", void 0, sourceFile);
|
|
3701
|
+
const classSymbol = typeChecker.tryGetMemberInModuleExports("Class", moduleSymbol);
|
|
3702
|
+
if (!classSymbol) return yield* typeParserIssue("Model's Class type not found", void 0, sourceFile);
|
|
3703
|
+
const makeRepositorySymbol = typeChecker.tryGetMemberInModuleExports("makeRepository", moduleSymbol);
|
|
3704
|
+
if (!makeRepositorySymbol) {
|
|
3705
|
+
return yield* typeParserIssue("Model's makeRepository type not found", void 0, sourceFile);
|
|
3706
|
+
}
|
|
3707
|
+
const makeDataLoadersSymbol = typeChecker.tryGetMemberInModuleExports("makeDataLoaders", moduleSymbol);
|
|
3708
|
+
if (!makeDataLoadersSymbol) {
|
|
3709
|
+
return yield* typeParserIssue("Model's makeDataLoaders type not found", void 0, sourceFile);
|
|
3710
|
+
}
|
|
3711
|
+
return sourceFile;
|
|
3712
|
+
}),
|
|
3713
|
+
"TypeParser.isEffectSqlModelTypeSourceFile",
|
|
3714
|
+
(sourceFile) => sourceFile
|
|
3715
|
+
);
|
|
3716
|
+
const isNodeReferenceToEffectSqlModelModuleApi = (memberName) => cachedBy(
|
|
3717
|
+
fn("TypeParser.isNodeReferenceToEffectSqlModelModuleApi")(function* (node) {
|
|
3718
|
+
return yield* isNodeReferenceToExportOfPackageModule(
|
|
3719
|
+
node,
|
|
3720
|
+
"@effect/sql",
|
|
3721
|
+
isEffectSqlModelTypeSourceFile,
|
|
3722
|
+
memberName
|
|
3723
|
+
);
|
|
3724
|
+
}),
|
|
3725
|
+
`TypeParser.isNodeReferenceToEffectSqlModelModuleApi(${memberName})`,
|
|
3726
|
+
(node) => node
|
|
3727
|
+
);
|
|
3728
|
+
const extendsEffectSqlModelClass = cachedBy(
|
|
3729
|
+
fn("TypeParser.extendsEffectSqlModelClass")(function* (atLocation) {
|
|
3730
|
+
if (!atLocation.name) {
|
|
3731
|
+
return yield* typeParserIssue("Class has no name", void 0, atLocation);
|
|
3732
|
+
}
|
|
3733
|
+
const heritageClauses = atLocation.heritageClauses;
|
|
3734
|
+
if (!heritageClauses) {
|
|
3735
|
+
return yield* typeParserIssue("Class has no heritage clauses", void 0, atLocation);
|
|
3736
|
+
}
|
|
3737
|
+
for (const heritageClause of heritageClauses) {
|
|
3738
|
+
for (const typeX of heritageClause.types) {
|
|
3739
|
+
if (ts.isExpressionWithTypeArguments(typeX)) {
|
|
3740
|
+
const expression = typeX.expression;
|
|
3741
|
+
if (ts.isCallExpression(expression)) {
|
|
3742
|
+
const schemaCall = expression.expression;
|
|
3743
|
+
if (ts.isCallExpression(schemaCall) && schemaCall.typeArguments && schemaCall.typeArguments.length > 0) {
|
|
3744
|
+
const isEffectSchemaModuleApi = yield* pipe(
|
|
3745
|
+
isNodeReferenceToEffectSqlModelModuleApi("Class")(schemaCall.expression),
|
|
3746
|
+
option
|
|
3747
|
+
);
|
|
3748
|
+
if (isSome2(isEffectSchemaModuleApi)) {
|
|
3749
|
+
return {
|
|
3750
|
+
className: atLocation.name,
|
|
3751
|
+
selfTypeNode: schemaCall.typeArguments[0]
|
|
3752
|
+
};
|
|
3753
|
+
}
|
|
3754
|
+
}
|
|
3755
|
+
}
|
|
3756
|
+
}
|
|
3757
|
+
}
|
|
3758
|
+
}
|
|
3759
|
+
return yield* typeParserIssue("Class does not extend @effect/sql's Model.Class", void 0, atLocation);
|
|
3760
|
+
}),
|
|
3761
|
+
"TypeParser.extendsEffectSqlModelClass",
|
|
3762
|
+
(atLocation) => atLocation
|
|
3763
|
+
);
|
|
3669
3764
|
return {
|
|
3670
3765
|
isNodeReferenceToEffectModuleApi,
|
|
3671
3766
|
isNodeReferenceToEffectSchemaModuleApi,
|
|
3672
3767
|
isNodeReferenceToEffectDataModuleApi,
|
|
3673
3768
|
isNodeReferenceToEffectContextModuleApi,
|
|
3769
|
+
isNodeReferenceToEffectSqlModelModuleApi,
|
|
3674
3770
|
effectType,
|
|
3675
3771
|
strictEffectType,
|
|
3676
3772
|
layerType,
|
|
@@ -3680,7 +3776,7 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
3680
3776
|
effectGen,
|
|
3681
3777
|
effectFnUntracedGen,
|
|
3682
3778
|
effectFnGen,
|
|
3683
|
-
|
|
3779
|
+
extendsCauseYieldableError,
|
|
3684
3780
|
unnecessaryEffectGen: unnecessaryEffectGen2,
|
|
3685
3781
|
effectSchemaType,
|
|
3686
3782
|
contextTag,
|
|
@@ -3696,7 +3792,8 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
3696
3792
|
extendsSchemaTaggedError,
|
|
3697
3793
|
extendsDataTaggedError,
|
|
3698
3794
|
extendsDataTaggedClass,
|
|
3699
|
-
extendsSchemaTaggedRequest
|
|
3795
|
+
extendsSchemaTaggedRequest,
|
|
3796
|
+
extendsEffectSqlModelClass
|
|
3700
3797
|
};
|
|
3701
3798
|
}
|
|
3702
3799
|
|
|
@@ -3704,10 +3801,12 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
3704
3801
|
var anyUnknownInErrorContext = createDiagnostic({
|
|
3705
3802
|
name: "anyUnknownInErrorContext",
|
|
3706
3803
|
code: 28,
|
|
3804
|
+
description: "Detects 'any' or 'unknown' types in Effect error or requirements channels",
|
|
3707
3805
|
severity: "off",
|
|
3708
3806
|
apply: fn("anyUnknownInErrorContext.apply")(function* (sourceFile, report) {
|
|
3709
3807
|
const ts = yield* service(TypeScriptApi);
|
|
3710
3808
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
3809
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
3711
3810
|
const typeParser = yield* service(TypeParser);
|
|
3712
3811
|
const isAnyOrUnknown = (type) => (type.flags & ts.TypeFlags.Any) > 0 || (type.flags & ts.TypeFlags.Unknown) > 0;
|
|
3713
3812
|
const matchingNodes = [];
|
|
@@ -3727,7 +3826,8 @@ var anyUnknownInErrorContext = createDiagnostic({
|
|
|
3727
3826
|
if (ts.isParameter(node) || ts.isPropertyDeclaration(node) || ts.isVariableDeclaration(node)) {
|
|
3728
3827
|
if (node.type) {
|
|
3729
3828
|
const typeNode = node.type;
|
|
3730
|
-
const type2 =
|
|
3829
|
+
const type2 = typeCheckerUtils.getTypeAtLocation(node.type);
|
|
3830
|
+
if (!type2) continue;
|
|
3731
3831
|
const expectedEffect = yield* pipe(
|
|
3732
3832
|
typeParser.strictEffectType(type2, node.type),
|
|
3733
3833
|
orElse2(() => typeParser.layerType(type2, typeNode)),
|
|
@@ -3738,11 +3838,7 @@ var anyUnknownInErrorContext = createDiagnostic({
|
|
|
3738
3838
|
}
|
|
3739
3839
|
ts.forEachChild(node, appendNodeToVisit);
|
|
3740
3840
|
if (!ts.isExpression(node)) continue;
|
|
3741
|
-
|
|
3742
|
-
if (node.parent && ts.isJsxOpeningElement(node.parent) && node.parent.tagName === node) continue;
|
|
3743
|
-
if (node.parent && ts.isJsxClosingElement(node.parent) && node.parent.tagName === node) continue;
|
|
3744
|
-
if (node.parent && ts.isJsxAttribute(node.parent) && node.parent.name === node) continue;
|
|
3745
|
-
let type = typeChecker.getTypeAtLocation(node);
|
|
3841
|
+
let type = typeCheckerUtils.getTypeAtLocation(node);
|
|
3746
3842
|
if (ts.isCallExpression(node)) {
|
|
3747
3843
|
const resolvedSignature = typeChecker.getResolvedSignature(node);
|
|
3748
3844
|
if (resolvedSignature) {
|
|
@@ -3808,11 +3904,13 @@ var anyUnknownInErrorContext = createDiagnostic({
|
|
|
3808
3904
|
var catchUnfailableEffect = createDiagnostic({
|
|
3809
3905
|
name: "catchUnfailableEffect",
|
|
3810
3906
|
code: 2,
|
|
3907
|
+
description: "Warns when using error handling on Effects that never fail (error type is 'never')",
|
|
3811
3908
|
severity: "suggestion",
|
|
3812
3909
|
apply: fn("catchUnfailableEffect.apply")(function* (sourceFile, report) {
|
|
3813
3910
|
const ts = yield* service(TypeScriptApi);
|
|
3814
3911
|
const typeParser = yield* service(TypeParser);
|
|
3815
3912
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
3913
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
3816
3914
|
const nodeToVisit = [];
|
|
3817
3915
|
const appendNodeToVisit = (node) => {
|
|
3818
3916
|
nodeToVisit.push(node);
|
|
@@ -3843,7 +3941,7 @@ var catchUnfailableEffect = createDiagnostic({
|
|
|
3843
3941
|
if (argIndex !== -1) {
|
|
3844
3942
|
let effectTypeToCheck;
|
|
3845
3943
|
if (argIndex === 0) {
|
|
3846
|
-
effectTypeToCheck =
|
|
3944
|
+
effectTypeToCheck = typeCheckerUtils.getTypeAtLocation(subject);
|
|
3847
3945
|
} else {
|
|
3848
3946
|
const signature = typeChecker.getResolvedSignature(pipeCallNode);
|
|
3849
3947
|
if (signature) {
|
|
@@ -3882,6 +3980,7 @@ var catchUnfailableEffect = createDiagnostic({
|
|
|
3882
3980
|
var classSelfMismatch = createDiagnostic({
|
|
3883
3981
|
name: "classSelfMismatch",
|
|
3884
3982
|
code: 20,
|
|
3983
|
+
description: "Ensures Self type parameter matches the class name in Service/Tag/Schema classes",
|
|
3885
3984
|
severity: "error",
|
|
3886
3985
|
apply: fn("classSelfMismatch.apply")(function* (sourceFile, report) {
|
|
3887
3986
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -3903,6 +4002,7 @@ var classSelfMismatch = createDiagnostic({
|
|
|
3903
4002
|
orElse2(() => typeParser.extendsSchemaTaggedClass(node)),
|
|
3904
4003
|
orElse2(() => typeParser.extendsSchemaTaggedError(node)),
|
|
3905
4004
|
orElse2(() => typeParser.extendsSchemaTaggedRequest(node)),
|
|
4005
|
+
orElse2(() => typeParser.extendsEffectSqlModelClass(node)),
|
|
3906
4006
|
orElse2(() => void_)
|
|
3907
4007
|
);
|
|
3908
4008
|
if (result) {
|
|
@@ -4012,6 +4112,7 @@ function createString(sourceFile, identifier, kind) {
|
|
|
4012
4112
|
var deterministicKeys = createDiagnostic({
|
|
4013
4113
|
name: "deterministicKeys",
|
|
4014
4114
|
code: 25,
|
|
4115
|
+
description: "Enforces deterministic naming for service/tag/error identifiers based on class names",
|
|
4015
4116
|
severity: "off",
|
|
4016
4117
|
apply: fn("deterministicKeys.apply")(function* (sourceFile, report) {
|
|
4017
4118
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -4132,6 +4233,7 @@ var programResolvedCacheSize = /* @__PURE__ */ new Map();
|
|
|
4132
4233
|
var duplicatePackage = createDiagnostic({
|
|
4133
4234
|
name: "duplicatePackage",
|
|
4134
4235
|
code: 6,
|
|
4236
|
+
description: "Detects when multiple versions of the same Effect package are loaded",
|
|
4135
4237
|
severity: "warning",
|
|
4136
4238
|
apply: fn("duplicatePackage.apply")(function* (sourceFile, report) {
|
|
4137
4239
|
const program = yield* service(TypeScriptProgram);
|
|
@@ -4179,6 +4281,7 @@ ${versions.map((version) => `- found ${version} at ${resolvedPackages[packageNam
|
|
|
4179
4281
|
var effectGenUsesAdapter = createDiagnostic({
|
|
4180
4282
|
name: "effectGenUsesAdapter",
|
|
4181
4283
|
code: 23,
|
|
4284
|
+
description: "Warns when using the deprecated adapter parameter in Effect.gen",
|
|
4182
4285
|
severity: "warning",
|
|
4183
4286
|
apply: fn("effectGenUsesAdapter.apply")(function* (sourceFile, report) {
|
|
4184
4287
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -4216,6 +4319,7 @@ var effectGenUsesAdapter = createDiagnostic({
|
|
|
4216
4319
|
var effectInVoidSuccess = createDiagnostic({
|
|
4217
4320
|
name: "effectInVoidSuccess",
|
|
4218
4321
|
code: 14,
|
|
4322
|
+
description: "Detects nested Effects in void success channels that may cause unexecuted effects",
|
|
4219
4323
|
severity: "warning",
|
|
4220
4324
|
apply: fn("effectInVoidSuccess.apply")(function* (sourceFile, report) {
|
|
4221
4325
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -4264,10 +4368,12 @@ var effectInVoidSuccess = createDiagnostic({
|
|
|
4264
4368
|
var floatingEffect = createDiagnostic({
|
|
4265
4369
|
name: "floatingEffect",
|
|
4266
4370
|
code: 3,
|
|
4371
|
+
description: "Ensures Effects are yielded or assigned to variables, not left floating",
|
|
4267
4372
|
severity: "error",
|
|
4268
4373
|
apply: fn("floatingEffect.apply")(function* (sourceFile, report) {
|
|
4269
4374
|
const ts = yield* service(TypeScriptApi);
|
|
4270
4375
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
4376
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
4271
4377
|
const typeParser = yield* service(TypeParser);
|
|
4272
4378
|
function isFloatingExpression(node) {
|
|
4273
4379
|
if (!ts.isExpressionStatement(node)) return false;
|
|
@@ -4286,7 +4392,8 @@ var floatingEffect = createDiagnostic({
|
|
|
4286
4392
|
const node = nodeToVisit.shift();
|
|
4287
4393
|
ts.forEachChild(node, appendNodeToVisit);
|
|
4288
4394
|
if (!isFloatingExpression(node)) continue;
|
|
4289
|
-
const type =
|
|
4395
|
+
const type = typeCheckerUtils.getTypeAtLocation(node.expression);
|
|
4396
|
+
if (!type) continue;
|
|
4290
4397
|
const effect = yield* option(typeParser.effectType(type, node.expression));
|
|
4291
4398
|
if (isSome2(effect)) {
|
|
4292
4399
|
const allowedFloatingEffects = yield* pipe(
|
|
@@ -4312,6 +4419,7 @@ var floatingEffect = createDiagnostic({
|
|
|
4312
4419
|
var genericEffectServices = createDiagnostic({
|
|
4313
4420
|
name: "genericEffectServices",
|
|
4314
4421
|
code: 10,
|
|
4422
|
+
description: "Prevents services with type parameters that cannot be discriminated at runtime",
|
|
4315
4423
|
severity: "warning",
|
|
4316
4424
|
apply: fn("genericEffectServices.apply")(function* (sourceFile, report) {
|
|
4317
4425
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -4354,10 +4462,56 @@ var genericEffectServices = createDiagnostic({
|
|
|
4354
4462
|
})
|
|
4355
4463
|
});
|
|
4356
4464
|
|
|
4465
|
+
// src/diagnostics/globalErrorInEffectFailure.ts
|
|
4466
|
+
var globalErrorInEffectFailure = createDiagnostic({
|
|
4467
|
+
name: "globalErrorInEffectFailure",
|
|
4468
|
+
code: 35,
|
|
4469
|
+
description: "Warns when Effect.fail is called with the global Error type",
|
|
4470
|
+
severity: "warning",
|
|
4471
|
+
apply: fn("globalErrorInEffectFailure.apply")(function* (sourceFile, report) {
|
|
4472
|
+
const ts = yield* service(TypeScriptApi);
|
|
4473
|
+
const typeParser = yield* service(TypeParser);
|
|
4474
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
4475
|
+
const nodeToVisit = [];
|
|
4476
|
+
const appendNodeToVisit = (node) => {
|
|
4477
|
+
nodeToVisit.push(node);
|
|
4478
|
+
return void 0;
|
|
4479
|
+
};
|
|
4480
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
4481
|
+
while (nodeToVisit.length > 0) {
|
|
4482
|
+
const node = nodeToVisit.shift();
|
|
4483
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
4484
|
+
if (ts.isCallExpression(node)) {
|
|
4485
|
+
yield* pipe(
|
|
4486
|
+
typeParser.isNodeReferenceToEffectModuleApi("fail")(node.expression),
|
|
4487
|
+
flatMap2(() => {
|
|
4488
|
+
if (node.arguments.length > 0) {
|
|
4489
|
+
const failArgument = node.arguments[0];
|
|
4490
|
+
const argumentType = typeCheckerUtils.getTypeAtLocation(failArgument);
|
|
4491
|
+
if (argumentType && typeCheckerUtils.isGlobalErrorType(argumentType)) {
|
|
4492
|
+
return sync(
|
|
4493
|
+
() => report({
|
|
4494
|
+
location: node,
|
|
4495
|
+
messageText: `Effect.fail is called with the global Error type. It's not recommended to use the global Error type in Effect failures as they can get merged together. Instead, use tagged errors (Data.TaggedError) or custom errors with a discriminator property to get properly type-checked errors.`,
|
|
4496
|
+
fixes: []
|
|
4497
|
+
})
|
|
4498
|
+
);
|
|
4499
|
+
}
|
|
4500
|
+
}
|
|
4501
|
+
return void_;
|
|
4502
|
+
}),
|
|
4503
|
+
ignore
|
|
4504
|
+
);
|
|
4505
|
+
}
|
|
4506
|
+
}
|
|
4507
|
+
})
|
|
4508
|
+
});
|
|
4509
|
+
|
|
4357
4510
|
// src/diagnostics/importFromBarrel.ts
|
|
4358
4511
|
var importFromBarrel = createDiagnostic({
|
|
4359
4512
|
name: "importFromBarrel",
|
|
4360
4513
|
code: 12,
|
|
4514
|
+
description: "Suggests importing from specific module paths instead of barrel exports",
|
|
4361
4515
|
severity: "off",
|
|
4362
4516
|
apply: fn("importFromBarrel.apply")(function* (sourceFile, report) {
|
|
4363
4517
|
const languageServicePluginOptions = yield* service(LanguageServicePluginOptions);
|
|
@@ -4497,6 +4651,7 @@ var importFromBarrel = createDiagnostic({
|
|
|
4497
4651
|
var leakingRequirements = createDiagnostic({
|
|
4498
4652
|
name: "leakingRequirements",
|
|
4499
4653
|
code: 8,
|
|
4654
|
+
description: "Detects implementation services leaked in service methods",
|
|
4500
4655
|
severity: "suggestion",
|
|
4501
4656
|
apply: fn("leakingRequirements.apply")(function* (sourceFile, report) {
|
|
4502
4657
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -4604,7 +4759,8 @@ More info at https://effect.website/docs/requirements-management/layers/#avoidin
|
|
|
4604
4759
|
const node = nodeToVisit.shift();
|
|
4605
4760
|
const typesToCheck = [];
|
|
4606
4761
|
if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.isIdentifier(node.expression.name) && ts.idText(node.expression.name) === "GenericTag") {
|
|
4607
|
-
|
|
4762
|
+
const nodeType = typeCheckerUtils.getTypeAtLocation(node);
|
|
4763
|
+
if (nodeType) typesToCheck.push([nodeType, node]);
|
|
4608
4764
|
} else if (ts.isClassDeclaration(node) && node.name && node.heritageClauses) {
|
|
4609
4765
|
const classSym = typeChecker.getSymbolAtLocation(node.name);
|
|
4610
4766
|
if (classSym) {
|
|
@@ -4638,10 +4794,12 @@ More info at https://effect.website/docs/requirements-management/layers/#avoidin
|
|
|
4638
4794
|
var missedPipeableOpportunity = createDiagnostic({
|
|
4639
4795
|
name: "missedPipeableOpportunity",
|
|
4640
4796
|
code: 26,
|
|
4797
|
+
description: "Enforces the use of pipeable style for nested function calls",
|
|
4641
4798
|
severity: "off",
|
|
4642
4799
|
apply: fn("missedPipeableOpportunity.apply")(function* (sourceFile, report) {
|
|
4643
4800
|
const ts = yield* service(TypeScriptApi);
|
|
4644
4801
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
4802
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
4645
4803
|
const typeParser = yield* service(TypeParser);
|
|
4646
4804
|
const options = yield* service(LanguageServicePluginOptions);
|
|
4647
4805
|
const nodeToVisit = [sourceFile];
|
|
@@ -4672,7 +4830,8 @@ var missedPipeableOpportunity = createDiagnostic({
|
|
|
4672
4830
|
const originalParentChain = parentChain.slice();
|
|
4673
4831
|
while (parentChain.length > options.pipeableMinArgCount) {
|
|
4674
4832
|
const subject = parentChain.pop();
|
|
4675
|
-
const resultType =
|
|
4833
|
+
const resultType = typeCheckerUtils.getTypeAtLocation(subject);
|
|
4834
|
+
if (!resultType) continue;
|
|
4676
4835
|
const pipeableType = yield* pipe(typeParser.pipeableType(resultType, subject), orElse2(() => void_));
|
|
4677
4836
|
if (pipeableType) {
|
|
4678
4837
|
report({
|
|
@@ -4717,6 +4876,7 @@ var missedPipeableOpportunity = createDiagnostic({
|
|
|
4717
4876
|
var missingEffectContext = createDiagnostic({
|
|
4718
4877
|
name: "missingEffectContext",
|
|
4719
4878
|
code: 1,
|
|
4879
|
+
description: "Reports missing service requirements in Effect context channel",
|
|
4720
4880
|
severity: "error",
|
|
4721
4881
|
apply: fn("missingEffectContext.apply")(function* (sourceFile, report) {
|
|
4722
4882
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
@@ -4765,6 +4925,7 @@ var missingEffectContext = createDiagnostic({
|
|
|
4765
4925
|
var missingEffectError = createDiagnostic({
|
|
4766
4926
|
name: "missingEffectError",
|
|
4767
4927
|
code: 1,
|
|
4928
|
+
description: "Reports missing error types in Effect error channel",
|
|
4768
4929
|
severity: "error",
|
|
4769
4930
|
apply: fn("missingEffectError.apply")(function* (sourceFile, report) {
|
|
4770
4931
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -4904,6 +5065,7 @@ var missingEffectError = createDiagnostic({
|
|
|
4904
5065
|
var missingEffectServiceDependency = createDiagnostic({
|
|
4905
5066
|
name: "missingEffectServiceDependency",
|
|
4906
5067
|
code: 22,
|
|
5068
|
+
description: "Checks that Effect.Service dependencies satisfy all required layer inputs",
|
|
4907
5069
|
severity: "off",
|
|
4908
5070
|
apply: fn("missingEffectServiceDependency.apply")(function* (sourceFile, report) {
|
|
4909
5071
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -4945,13 +5107,15 @@ var missingEffectServiceDependency = createDiagnostic({
|
|
|
4945
5107
|
excludeNever
|
|
4946
5108
|
);
|
|
4947
5109
|
const providedIndexes = /* @__PURE__ */ new Set();
|
|
4948
|
-
const optionsType = typeChecker.getTypeAtLocation(options);
|
|
4949
|
-
const dependenciesProperty = typeChecker.getPropertyOfType(optionsType, "dependencies");
|
|
4950
5110
|
let types = [];
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
const
|
|
4954
|
-
|
|
5111
|
+
const optionsType = typeCheckerUtils.getTypeAtLocation(options);
|
|
5112
|
+
if (optionsType) {
|
|
5113
|
+
const dependenciesProperty = typeChecker.getPropertyOfType(optionsType, "dependencies");
|
|
5114
|
+
if (dependenciesProperty) {
|
|
5115
|
+
const dependenciesTypes = typeChecker.getTypeOfSymbolAtLocation(dependenciesProperty, options);
|
|
5116
|
+
const numberIndexType = typeChecker.getIndexTypeOfType(dependenciesTypes, ts.IndexKind.Number);
|
|
5117
|
+
types = numberIndexType ? typeCheckerUtils.unrollUnionMembers(numberIndexType) : [];
|
|
5118
|
+
}
|
|
4955
5119
|
}
|
|
4956
5120
|
for (const depType of types) {
|
|
4957
5121
|
const depLayerResult = yield* pipe(
|
|
@@ -4994,10 +5158,11 @@ var missingEffectServiceDependency = createDiagnostic({
|
|
|
4994
5158
|
var missingReturnYieldStar = createDiagnostic({
|
|
4995
5159
|
name: "missingReturnYieldStar",
|
|
4996
5160
|
code: 7,
|
|
5161
|
+
description: "Suggests using 'return yield*' for Effects with never success for better type narrowing",
|
|
4997
5162
|
severity: "error",
|
|
4998
5163
|
apply: fn("missingReturnYieldStar.apply")(function* (sourceFile, report) {
|
|
4999
5164
|
const ts = yield* service(TypeScriptApi);
|
|
5000
|
-
const
|
|
5165
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
5001
5166
|
const typeParser = yield* service(TypeParser);
|
|
5002
5167
|
const nodeToVisit = [];
|
|
5003
5168
|
const appendNodeToVisit = (node) => {
|
|
@@ -5009,42 +5174,44 @@ var missingReturnYieldStar = createDiagnostic({
|
|
|
5009
5174
|
const node = nodeToVisit.shift();
|
|
5010
5175
|
ts.forEachChild(node, appendNodeToVisit);
|
|
5011
5176
|
if (ts.isYieldExpression(node) && node.expression && node.asteriskToken) {
|
|
5012
|
-
const type =
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
if (generatorFunctionOrReturnStatement && generatorFunctionOrReturnStatement.
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5177
|
+
const type = typeCheckerUtils.getTypeAtLocation(node.expression);
|
|
5178
|
+
if (type) {
|
|
5179
|
+
const maybeEffect = yield* option(typeParser.effectType(type, node.expression));
|
|
5180
|
+
if (isSome2(maybeEffect) && maybeEffect.value.A.flags & ts.TypeFlags.Never) {
|
|
5181
|
+
const generatorFunctionOrReturnStatement = ts.findAncestor(
|
|
5182
|
+
node,
|
|
5183
|
+
(_) => ts.isFunctionExpression(_) || ts.isFunctionDeclaration(_) || ts.isMethodDeclaration(_) || ts.isReturnStatement(_) || ts.isThrowStatement(_)
|
|
5184
|
+
);
|
|
5185
|
+
if (generatorFunctionOrReturnStatement && !ts.isReturnStatement(generatorFunctionOrReturnStatement) && !ts.isThrowStatement(generatorFunctionOrReturnStatement)) {
|
|
5186
|
+
if (generatorFunctionOrReturnStatement && generatorFunctionOrReturnStatement.parent) {
|
|
5187
|
+
const effectGenNode = generatorFunctionOrReturnStatement.parent;
|
|
5188
|
+
const effectGenLike = yield* pipe(
|
|
5189
|
+
typeParser.effectGen(effectGenNode),
|
|
5190
|
+
orElse2(() => typeParser.effectFnUntracedGen(effectGenNode)),
|
|
5191
|
+
orElse2(() => typeParser.effectFnGen(effectGenNode)),
|
|
5192
|
+
option
|
|
5193
|
+
);
|
|
5194
|
+
if (isSome2(effectGenLike)) {
|
|
5195
|
+
const fix = node.expression ? [{
|
|
5196
|
+
fixName: "missingReturnYieldStar_fix",
|
|
5197
|
+
description: "Add return statement",
|
|
5198
|
+
apply: gen(function* () {
|
|
5199
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
5200
|
+
changeTracker.replaceNode(
|
|
5201
|
+
sourceFile,
|
|
5202
|
+
node,
|
|
5203
|
+
ts.factory.createReturnStatement(
|
|
5204
|
+
node
|
|
5205
|
+
)
|
|
5206
|
+
);
|
|
5207
|
+
})
|
|
5208
|
+
}] : [];
|
|
5209
|
+
report({
|
|
5210
|
+
location: node,
|
|
5211
|
+
messageText: `It is recommended to use return yield* for Effects that never succeed to signal a definitive exit point for type narrowing and tooling support.`,
|
|
5212
|
+
fixes: fix
|
|
5213
|
+
});
|
|
5214
|
+
}
|
|
5048
5215
|
}
|
|
5049
5216
|
}
|
|
5050
5217
|
}
|
|
@@ -5058,6 +5225,7 @@ var missingReturnYieldStar = createDiagnostic({
|
|
|
5058
5225
|
var missingStarInYieldEffectGen = createDiagnostic({
|
|
5059
5226
|
name: "missingStarInYieldEffectGen",
|
|
5060
5227
|
code: 4,
|
|
5228
|
+
description: "Enforces using 'yield*' instead of 'yield' when yielding Effects in generators",
|
|
5061
5229
|
severity: "error",
|
|
5062
5230
|
apply: fn("missingStarInYieldEffectGen.apply")(function* (sourceFile, report) {
|
|
5063
5231
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -5132,11 +5300,12 @@ var missingStarInYieldEffectGen = createDiagnostic({
|
|
|
5132
5300
|
var multipleEffectProvide = createDiagnostic({
|
|
5133
5301
|
name: "multipleEffectProvide",
|
|
5134
5302
|
code: 18,
|
|
5303
|
+
description: "Warns against chaining Effect.provide calls which can cause service lifecycle issues",
|
|
5135
5304
|
severity: "warning",
|
|
5136
5305
|
apply: fn("multipleEffectProvide.apply")(function* (sourceFile, report) {
|
|
5137
5306
|
const ts = yield* service(TypeScriptApi);
|
|
5138
5307
|
const tsUtils = yield* service(TypeScriptUtils);
|
|
5139
|
-
const
|
|
5308
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
5140
5309
|
const typeParser = yield* service(TypeParser);
|
|
5141
5310
|
const effectModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
|
|
5142
5311
|
sourceFile,
|
|
@@ -5151,7 +5320,8 @@ var multipleEffectProvide = createDiagnostic({
|
|
|
5151
5320
|
const parseEffectProvideLayer = (node) => {
|
|
5152
5321
|
if (ts.isCallExpression(node) && node.arguments.length > 0) {
|
|
5153
5322
|
const layer = node.arguments[0];
|
|
5154
|
-
const type =
|
|
5323
|
+
const type = typeCheckerUtils.getTypeAtLocation(layer);
|
|
5324
|
+
if (!type) return void_;
|
|
5155
5325
|
return pipe(
|
|
5156
5326
|
typeParser.isNodeReferenceToEffectModuleApi("provide")(node.expression),
|
|
5157
5327
|
flatMap2(() => typeParser.layerType(type, layer)),
|
|
@@ -5229,6 +5399,7 @@ var multipleEffectProvide = createDiagnostic({
|
|
|
5229
5399
|
var nonObjectEffectServiceType = createDiagnostic({
|
|
5230
5400
|
name: "nonObjectEffectServiceType",
|
|
5231
5401
|
code: 24,
|
|
5402
|
+
description: "Ensures Effect.Service types are objects, not primitives",
|
|
5232
5403
|
severity: "error",
|
|
5233
5404
|
apply: fn("nonObjectEffectServiceType.apply")(function* (sourceFile, report) {
|
|
5234
5405
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -5267,12 +5438,13 @@ var nonObjectEffectServiceType = createDiagnostic({
|
|
|
5267
5438
|
fixes: []
|
|
5268
5439
|
};
|
|
5269
5440
|
if (propertyName === "succeed") {
|
|
5270
|
-
const valueType =
|
|
5271
|
-
if (isPrimitiveType(valueType)) {
|
|
5441
|
+
const valueType = typeCheckerUtils.getTypeAtLocation(propertyValue);
|
|
5442
|
+
if (valueType && isPrimitiveType(valueType)) {
|
|
5272
5443
|
report(errorToReport);
|
|
5273
5444
|
}
|
|
5274
5445
|
} else if (propertyName === "sync") {
|
|
5275
|
-
const valueType =
|
|
5446
|
+
const valueType = typeCheckerUtils.getTypeAtLocation(propertyValue);
|
|
5447
|
+
if (!valueType) continue;
|
|
5276
5448
|
const signatures = typeChecker.getSignaturesOfType(valueType, ts.SignatureKind.Call);
|
|
5277
5449
|
for (const signature of signatures) {
|
|
5278
5450
|
const returnType = typeChecker.getReturnTypeOfSignature(signature);
|
|
@@ -5282,7 +5454,8 @@ var nonObjectEffectServiceType = createDiagnostic({
|
|
|
5282
5454
|
}
|
|
5283
5455
|
}
|
|
5284
5456
|
} else if (propertyName === "effect" || propertyName === "scoped") {
|
|
5285
|
-
const valueType =
|
|
5457
|
+
const valueType = typeCheckerUtils.getTypeAtLocation(propertyValue);
|
|
5458
|
+
if (!valueType) continue;
|
|
5286
5459
|
const effectResult = yield* pipe(
|
|
5287
5460
|
typeParser.effectType(valueType, propertyValue),
|
|
5288
5461
|
orElse2(() => void_)
|
|
@@ -5629,7 +5802,8 @@ var annotate = createCodegen({
|
|
|
5629
5802
|
}
|
|
5630
5803
|
for (const variableDeclaration of variableDeclarations) {
|
|
5631
5804
|
if (!variableDeclaration.initializer) continue;
|
|
5632
|
-
const initializerType =
|
|
5805
|
+
const initializerType = typeCheckerUtils.getTypeAtLocation(variableDeclaration.initializer);
|
|
5806
|
+
if (!initializerType) continue;
|
|
5633
5807
|
const enclosingNode = ts.findAncestor(variableDeclaration, (_) => tsUtils.isDeclarationKind(_.kind)) || sourceFile;
|
|
5634
5808
|
const initializerTypeNode = fromNullable(typeCheckerUtils.typeToSimplifiedTypeNode(
|
|
5635
5809
|
initializerType,
|
|
@@ -6081,7 +6255,7 @@ var findNodeToProcess = fn("StructuralSchemaGen.findNodeToProcess")(
|
|
|
6081
6255
|
function* (sourceFile, textRange) {
|
|
6082
6256
|
const ts = yield* service(TypeScriptApi);
|
|
6083
6257
|
const tsUtils = yield* service(TypeScriptUtils);
|
|
6084
|
-
const
|
|
6258
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
6085
6259
|
return pipe(
|
|
6086
6260
|
tsUtils.getAncestorNodesInRange(sourceFile, textRange),
|
|
6087
6261
|
filter((node) => ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node)),
|
|
@@ -6090,7 +6264,7 @@ var findNodeToProcess = fn("StructuralSchemaGen.findNodeToProcess")(
|
|
|
6090
6264
|
map3((node) => ({
|
|
6091
6265
|
node,
|
|
6092
6266
|
identifier: node.name,
|
|
6093
|
-
type:
|
|
6267
|
+
type: typeCheckerUtils.getTypeAtLocation(node.name),
|
|
6094
6268
|
isExported: node.modifiers ? (ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export) !== 0 : false
|
|
6095
6269
|
})),
|
|
6096
6270
|
filter(({ type }) => !!type),
|
|
@@ -6268,7 +6442,7 @@ var typeToSchema = createCodegen({
|
|
|
6268
6442
|
)
|
|
6269
6443
|
);
|
|
6270
6444
|
}
|
|
6271
|
-
const type =
|
|
6445
|
+
const type = typeCheckerUtils.getTypeAtLocation(node.name);
|
|
6272
6446
|
if (!type) {
|
|
6273
6447
|
return yield* fail(
|
|
6274
6448
|
new CodegenNotApplicableError(
|
|
@@ -6349,6 +6523,7 @@ var codegens = [accessors, annotate, typeToSchema];
|
|
|
6349
6523
|
var outdatedEffectCodegen = createDiagnostic({
|
|
6350
6524
|
name: "outdatedEffectCodegen",
|
|
6351
6525
|
code: 19,
|
|
6526
|
+
description: "Detects when generated code is outdated and needs to be regenerated",
|
|
6352
6527
|
severity: "warning",
|
|
6353
6528
|
apply: fn("outdatedEffectCodegen.apply")(function* (sourceFile, _report) {
|
|
6354
6529
|
const codegensWithRanges = yield* getCodegensForSourceFile(codegens, sourceFile);
|
|
@@ -6394,11 +6569,12 @@ var outdatedEffectCodegen = createDiagnostic({
|
|
|
6394
6569
|
var overriddenSchemaConstructor = createDiagnostic({
|
|
6395
6570
|
name: "overriddenSchemaConstructor",
|
|
6396
6571
|
code: 30,
|
|
6572
|
+
description: "Prevents overriding constructors in Schema classes which breaks decoding behavior",
|
|
6397
6573
|
severity: "error",
|
|
6398
6574
|
apply: fn("overriddenSchemaConstructor.apply")(function* (sourceFile, report) {
|
|
6399
6575
|
const ts = yield* service(TypeScriptApi);
|
|
6400
6576
|
const typeParser = yield* service(TypeParser);
|
|
6401
|
-
const
|
|
6577
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
6402
6578
|
function isAllowedConstructor(node) {
|
|
6403
6579
|
if (node.body && node.body.statements.length === 1) {
|
|
6404
6580
|
const expressionStatement = node.body.statements[0];
|
|
@@ -6432,7 +6608,8 @@ var overriddenSchemaConstructor = createDiagnostic({
|
|
|
6432
6608
|
for (const heritageClause of node.heritageClauses) {
|
|
6433
6609
|
if (heritageClause.token === ts.SyntaxKind.ExtendsKeyword) {
|
|
6434
6610
|
for (const type of heritageClause.types) {
|
|
6435
|
-
const typeAtLocation =
|
|
6611
|
+
const typeAtLocation = typeCheckerUtils.getTypeAtLocation(type.expression);
|
|
6612
|
+
if (!typeAtLocation) continue;
|
|
6436
6613
|
const isSchema = yield* pipe(
|
|
6437
6614
|
typeParser.effectSchemaType(typeAtLocation, type.expression),
|
|
6438
6615
|
map4(() => true),
|
|
@@ -6529,10 +6706,11 @@ var overriddenSchemaConstructor = createDiagnostic({
|
|
|
6529
6706
|
var returnEffectInGen = createDiagnostic({
|
|
6530
6707
|
name: "returnEffectInGen",
|
|
6531
6708
|
code: 11,
|
|
6709
|
+
description: "Warns when returning an Effect in a generator causes nested Effect<Effect<...>>",
|
|
6532
6710
|
severity: "suggestion",
|
|
6533
6711
|
apply: fn("returnEffectInGen.apply")(function* (sourceFile, report) {
|
|
6534
6712
|
const ts = yield* service(TypeScriptApi);
|
|
6535
|
-
const
|
|
6713
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
6536
6714
|
const typeParser = yield* service(TypeParser);
|
|
6537
6715
|
const nodeToVisit = [];
|
|
6538
6716
|
const appendNodeToVisit = (node) => {
|
|
@@ -6550,7 +6728,8 @@ var returnEffectInGen = createDiagnostic({
|
|
|
6550
6728
|
(_) => ts.isFunctionExpression(_) || ts.isFunctionDeclaration(_) || ts.isMethodDeclaration(_) || ts.isArrowFunction(_) || ts.isGetAccessor(_)
|
|
6551
6729
|
);
|
|
6552
6730
|
if (!(generatorOrRegularFunction && "asteriskToken" in generatorOrRegularFunction && generatorOrRegularFunction.asteriskToken)) continue;
|
|
6553
|
-
const type =
|
|
6731
|
+
const type = typeCheckerUtils.getTypeAtLocation(node.expression);
|
|
6732
|
+
if (!type) continue;
|
|
6554
6733
|
const maybeEffect = yield* option(typeParser.strictEffectType(type, node.expression));
|
|
6555
6734
|
if (isSome2(maybeEffect)) {
|
|
6556
6735
|
if (generatorOrRegularFunction && generatorOrRegularFunction.parent) {
|
|
@@ -6596,6 +6775,7 @@ Nested Effect-able types may be intended if you plan to later manually flatten o
|
|
|
6596
6775
|
var runEffectInsideEffect = createDiagnostic({
|
|
6597
6776
|
name: "runEffectInsideEffect",
|
|
6598
6777
|
code: 32,
|
|
6778
|
+
description: "Suggests using Runtime methods instead of Effect.run* inside Effect contexts",
|
|
6599
6779
|
severity: "suggestion",
|
|
6600
6780
|
apply: fn("runEffectInsideEffect.apply")(function* (sourceFile, report) {
|
|
6601
6781
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -6735,6 +6915,7 @@ Consider extracting the Runtime by using for example Effect.runtime and then use
|
|
|
6735
6915
|
var schemaStructWithTag = createDiagnostic({
|
|
6736
6916
|
name: "schemaStructWithTag",
|
|
6737
6917
|
code: 34,
|
|
6918
|
+
description: "Suggests using Schema.TaggedStruct instead of Schema.Struct with _tag field",
|
|
6738
6919
|
severity: "suggestion",
|
|
6739
6920
|
apply: fn("schemaStructWithTag.apply")(function* (sourceFile, report) {
|
|
6740
6921
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -6814,6 +6995,7 @@ var schemaStructWithTag = createDiagnostic({
|
|
|
6814
6995
|
var schemaUnionOfLiterals = createDiagnostic({
|
|
6815
6996
|
name: "schemaUnionOfLiterals",
|
|
6816
6997
|
code: 33,
|
|
6998
|
+
description: "Simplifies Schema.Union of multiple Schema.Literal calls into single Schema.Literal",
|
|
6817
6999
|
severity: "off",
|
|
6818
7000
|
apply: fn("schemaUnionOfLiterals.apply")(function* (sourceFile, report) {
|
|
6819
7001
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -6887,6 +7069,7 @@ var schemaUnionOfLiterals = createDiagnostic({
|
|
|
6887
7069
|
var scopeInLayerEffect = createDiagnostic({
|
|
6888
7070
|
name: "scopeInLayerEffect",
|
|
6889
7071
|
code: 13,
|
|
7072
|
+
description: "Suggests using Layer.scoped instead of Layer.effect when Scope is in requirements",
|
|
6890
7073
|
severity: "warning",
|
|
6891
7074
|
apply: fn("scopeInLayerEffect.apply")(function* (sourceFile, report) {
|
|
6892
7075
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -6945,12 +7128,14 @@ Consider using "scoped" instead to get rid of the scope in the requirements.`,
|
|
|
6945
7128
|
const node = nodeToVisit.shift();
|
|
6946
7129
|
const layerEffectApiCall = parseLayerEffectApiCall(node);
|
|
6947
7130
|
if (layerEffectApiCall) {
|
|
6948
|
-
const type =
|
|
6949
|
-
|
|
6950
|
-
|
|
6951
|
-
|
|
6952
|
-
|
|
6953
|
-
|
|
7131
|
+
const type = typeCheckerUtils.getTypeAtLocation(node);
|
|
7132
|
+
if (type) {
|
|
7133
|
+
yield* pipe(
|
|
7134
|
+
typeParser.layerType(type, node),
|
|
7135
|
+
flatMap2(({ RIn }) => reportIfLayerRequireScope(RIn, node, layerEffectApiCall.methodIdentifier)),
|
|
7136
|
+
ignore
|
|
7137
|
+
);
|
|
7138
|
+
}
|
|
6954
7139
|
continue;
|
|
6955
7140
|
}
|
|
6956
7141
|
if (ts.isClassDeclaration(node) && node.name && node.heritageClauses) {
|
|
@@ -6978,6 +7163,7 @@ Consider using "scoped" instead to get rid of the scope in the requirements.`,
|
|
|
6978
7163
|
var strictBooleanExpressions = createDiagnostic({
|
|
6979
7164
|
name: "strictBooleanExpressions",
|
|
6980
7165
|
code: 17,
|
|
7166
|
+
description: "Enforces boolean types in conditional expressions for type safety",
|
|
6981
7167
|
severity: "off",
|
|
6982
7168
|
apply: fn("strictBooleanExpressions.apply")(function* (sourceFile, report) {
|
|
6983
7169
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -7019,7 +7205,8 @@ var strictBooleanExpressions = createDiagnostic({
|
|
|
7019
7205
|
if (!nodeToCheck) continue;
|
|
7020
7206
|
if (!conditionChecks.has(nodeToCheck.parent)) continue;
|
|
7021
7207
|
if (!ts.isExpression(nodeToCheck)) continue;
|
|
7022
|
-
const nodeType =
|
|
7208
|
+
const nodeType = typeCheckerUtils.getTypeAtLocation(nodeToCheck);
|
|
7209
|
+
if (!nodeType) continue;
|
|
7023
7210
|
const constrainedType = typeChecker.getBaseConstraintOfType(nodeType);
|
|
7024
7211
|
let typesToCheck = [constrainedType || nodeType];
|
|
7025
7212
|
while (typesToCheck.length > 0) {
|
|
@@ -7047,10 +7234,11 @@ var strictBooleanExpressions = createDiagnostic({
|
|
|
7047
7234
|
var strictEffectProvide = createDiagnostic({
|
|
7048
7235
|
name: "strictEffectProvide",
|
|
7049
7236
|
code: 27,
|
|
7237
|
+
description: "Warns when using Effect.provide with layers outside of application entry points",
|
|
7050
7238
|
severity: "off",
|
|
7051
7239
|
apply: fn("strictEffectProvide.apply")(function* (sourceFile, report) {
|
|
7052
7240
|
const ts = yield* service(TypeScriptApi);
|
|
7053
|
-
const
|
|
7241
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
7054
7242
|
const typeParser = yield* service(TypeParser);
|
|
7055
7243
|
const parseEffectProvideWithLayer = (node) => gen(function* () {
|
|
7056
7244
|
if (!ts.isCallExpression(node) || node.arguments.length === 0) {
|
|
@@ -7059,7 +7247,8 @@ var strictEffectProvide = createDiagnostic({
|
|
|
7059
7247
|
yield* typeParser.isNodeReferenceToEffectModuleApi("provide")(node.expression);
|
|
7060
7248
|
return yield* firstSuccessOf(
|
|
7061
7249
|
node.arguments.map((arg) => {
|
|
7062
|
-
const argType =
|
|
7250
|
+
const argType = typeCheckerUtils.getTypeAtLocation(arg);
|
|
7251
|
+
if (!argType) return typeParserIssue("Could not get argument type");
|
|
7063
7252
|
return typeParser.layerType(argType, arg);
|
|
7064
7253
|
})
|
|
7065
7254
|
);
|
|
@@ -7091,6 +7280,7 @@ var strictEffectProvide = createDiagnostic({
|
|
|
7091
7280
|
var tryCatchInEffectGen = createDiagnostic({
|
|
7092
7281
|
name: "tryCatchInEffectGen",
|
|
7093
7282
|
code: 15,
|
|
7283
|
+
description: "Discourages try/catch in Effect generators in favor of Effect error handling",
|
|
7094
7284
|
severity: "suggestion",
|
|
7095
7285
|
apply: fn("tryCatchInEffectGen.apply")(function* (sourceFile, report) {
|
|
7096
7286
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -7136,6 +7326,7 @@ var tryCatchInEffectGen = createDiagnostic({
|
|
|
7136
7326
|
var unknownInEffectCatch = createDiagnostic({
|
|
7137
7327
|
name: "unknownInEffectCatch",
|
|
7138
7328
|
code: 31,
|
|
7329
|
+
description: "Warns when catch callbacks return unknown instead of typed errors",
|
|
7139
7330
|
severity: "warning",
|
|
7140
7331
|
apply: fn("unknownInEffectCatch.apply")(function* (sourceFile, report) {
|
|
7141
7332
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -7193,6 +7384,7 @@ Consider wrapping unknown errors into Effect's Data.TaggedError for example, or
|
|
|
7193
7384
|
var unnecessaryEffectGen = createDiagnostic({
|
|
7194
7385
|
name: "unnecessaryEffectGen",
|
|
7195
7386
|
code: 5,
|
|
7387
|
+
description: "Suggests removing Effect.gen when it contains only a single return statement",
|
|
7196
7388
|
severity: "suggestion",
|
|
7197
7389
|
apply: fn("unnecessaryEffectGen.apply")(function* (sourceFile, report) {
|
|
7198
7390
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -7236,15 +7428,12 @@ var unnecessaryEffectGen = createDiagnostic({
|
|
|
7236
7428
|
var unnecessaryFailYieldableError = createDiagnostic({
|
|
7237
7429
|
name: "unnecessaryFailYieldableError",
|
|
7238
7430
|
code: 29,
|
|
7431
|
+
description: "Suggests yielding yieldable errors directly instead of wrapping with Effect.fail",
|
|
7239
7432
|
severity: "suggestion",
|
|
7240
7433
|
apply: fn("unnecessaryFailYieldableError.apply")(function* (sourceFile, report) {
|
|
7241
7434
|
const ts = yield* service(TypeScriptApi);
|
|
7242
7435
|
const typeParser = yield* service(TypeParser);
|
|
7243
|
-
const
|
|
7244
|
-
const yieldableErrorTypes = yield* pipe(
|
|
7245
|
-
typeParser.effectCauseYieldableErrorTypes(sourceFile),
|
|
7246
|
-
orElse2(() => succeed([]))
|
|
7247
|
-
);
|
|
7436
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
7248
7437
|
const nodeToVisit = [];
|
|
7249
7438
|
const appendNodeToVisit = (node) => {
|
|
7250
7439
|
nodeToVisit.push(node);
|
|
@@ -7258,32 +7447,34 @@ var unnecessaryFailYieldableError = createDiagnostic({
|
|
|
7258
7447
|
const callExpression = node.expression;
|
|
7259
7448
|
yield* pipe(
|
|
7260
7449
|
typeParser.isNodeReferenceToEffectModuleApi("fail")(callExpression.expression),
|
|
7261
|
-
|
|
7450
|
+
flatMap2(() => {
|
|
7262
7451
|
if (callExpression.arguments.length > 0) {
|
|
7263
7452
|
const failArgument = callExpression.arguments[0];
|
|
7264
|
-
const argumentType =
|
|
7265
|
-
|
|
7266
|
-
|
|
7453
|
+
const argumentType = typeCheckerUtils.getTypeAtLocation(failArgument);
|
|
7454
|
+
if (!argumentType) return void_;
|
|
7455
|
+
return pipe(
|
|
7456
|
+
typeParser.extendsCauseYieldableError(argumentType),
|
|
7457
|
+
map4(
|
|
7458
|
+
() => report({
|
|
7459
|
+
location: node,
|
|
7460
|
+
messageText: `This Effect.fail call uses a yieldable error type as argument. You can yield* the error directly instead.`,
|
|
7461
|
+
fixes: [{
|
|
7462
|
+
fixName: "unnecessaryFailYieldableError_fix",
|
|
7463
|
+
description: "Replace yield* Effect.fail with yield*",
|
|
7464
|
+
apply: gen(function* () {
|
|
7465
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
7466
|
+
changeTracker.replaceNode(
|
|
7467
|
+
sourceFile,
|
|
7468
|
+
callExpression,
|
|
7469
|
+
failArgument
|
|
7470
|
+
);
|
|
7471
|
+
})
|
|
7472
|
+
}]
|
|
7473
|
+
})
|
|
7474
|
+
)
|
|
7267
7475
|
);
|
|
7268
|
-
if (isYieldableError) {
|
|
7269
|
-
report({
|
|
7270
|
-
location: node,
|
|
7271
|
-
messageText: `This Effect.fail call uses a yieldable error type as argument. You can yield* the error directly instead.`,
|
|
7272
|
-
fixes: [{
|
|
7273
|
-
fixName: "unnecessaryFailYieldableError_fix",
|
|
7274
|
-
description: "Replace yield* Effect.fail with yield*",
|
|
7275
|
-
apply: gen(function* () {
|
|
7276
|
-
const changeTracker = yield* service(ChangeTracker);
|
|
7277
|
-
changeTracker.replaceNode(
|
|
7278
|
-
sourceFile,
|
|
7279
|
-
callExpression,
|
|
7280
|
-
failArgument
|
|
7281
|
-
);
|
|
7282
|
-
})
|
|
7283
|
-
}]
|
|
7284
|
-
});
|
|
7285
|
-
}
|
|
7286
7476
|
}
|
|
7477
|
+
return void_;
|
|
7287
7478
|
}),
|
|
7288
7479
|
ignore
|
|
7289
7480
|
);
|
|
@@ -7296,6 +7487,7 @@ var unnecessaryFailYieldableError = createDiagnostic({
|
|
|
7296
7487
|
var unnecessaryPipe = createDiagnostic({
|
|
7297
7488
|
name: "unnecessaryPipe",
|
|
7298
7489
|
code: 9,
|
|
7490
|
+
description: "Removes pipe calls with no arguments",
|
|
7299
7491
|
severity: "suggestion",
|
|
7300
7492
|
apply: fn("unnecessaryPipe.apply")(function* (sourceFile, report) {
|
|
7301
7493
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -7341,6 +7533,7 @@ var unnecessaryPipe = createDiagnostic({
|
|
|
7341
7533
|
var unnecessaryPipeChain = createDiagnostic({
|
|
7342
7534
|
name: "unnecessaryPipeChain",
|
|
7343
7535
|
code: 16,
|
|
7536
|
+
description: "Simplifies chained pipe calls into a single pipe call",
|
|
7344
7537
|
severity: "suggestion",
|
|
7345
7538
|
apply: fn("unnecessaryPipeChain.apply")(function* (sourceFile, report) {
|
|
7346
7539
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -7415,6 +7608,7 @@ var unnecessaryPipeChain = createDiagnostic({
|
|
|
7415
7608
|
var unsupportedServiceAccessors = createDiagnostic({
|
|
7416
7609
|
name: "unsupportedServiceAccessors",
|
|
7417
7610
|
code: 21,
|
|
7611
|
+
description: "Warns about service accessors that need codegen due to generic/complex signatures",
|
|
7418
7612
|
severity: "warning",
|
|
7419
7613
|
apply: fn("unsupportedServiceAccessors.apply")(function* (sourceFile, report) {
|
|
7420
7614
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -7502,7 +7696,8 @@ var diagnostics = [
|
|
|
7502
7696
|
unknownInEffectCatch,
|
|
7503
7697
|
runEffectInsideEffect,
|
|
7504
7698
|
schemaUnionOfLiterals,
|
|
7505
|
-
schemaStructWithTag
|
|
7699
|
+
schemaStructWithTag,
|
|
7700
|
+
globalErrorInEffectFailure
|
|
7506
7701
|
];
|
|
7507
7702
|
|
|
7508
7703
|
// src/effect-lsp-patch-utils.ts
|