@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
package/transform.js
CHANGED
|
@@ -24,7 +24,7 @@ __export(transform_exports, {
|
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(transform_exports);
|
|
26
26
|
|
|
27
|
-
// node_modules/.pnpm/effect@3.19.
|
|
27
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Function.js
|
|
28
28
|
var isFunction = (input) => typeof input === "function";
|
|
29
29
|
var dual = function(arity, body) {
|
|
30
30
|
if (typeof arity === "function") {
|
|
@@ -120,7 +120,7 @@ function pipe(a, ab, bc, cd, de, ef, fg, gh, hi) {
|
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
// node_modules/.pnpm/effect@3.19.
|
|
123
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/GlobalValue.js
|
|
124
124
|
var globalStoreId = `effect/GlobalValue`;
|
|
125
125
|
var globalStore;
|
|
126
126
|
var globalValue = (id, compute) => {
|
|
@@ -134,7 +134,7 @@ var globalValue = (id, compute) => {
|
|
|
134
134
|
return globalStore.get(id);
|
|
135
135
|
};
|
|
136
136
|
|
|
137
|
-
// node_modules/.pnpm/effect@3.19.
|
|
137
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Predicate.js
|
|
138
138
|
var isString = (input) => typeof input === "string";
|
|
139
139
|
var isNumber = (input) => typeof input === "number";
|
|
140
140
|
var isBoolean = (input) => typeof input === "boolean";
|
|
@@ -144,7 +144,7 @@ var isObject = (input) => isRecordOrArray(input) || isFunction2(input);
|
|
|
144
144
|
var hasProperty = /* @__PURE__ */ dual(2, (self, property) => isObject(self) && property in self);
|
|
145
145
|
var isRecord = (input) => isRecordOrArray(input) && !Array.isArray(input);
|
|
146
146
|
|
|
147
|
-
// node_modules/.pnpm/effect@3.19.
|
|
147
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Utils.js
|
|
148
148
|
var GenKindTypeId = /* @__PURE__ */ Symbol.for("effect/Gen/GenKind");
|
|
149
149
|
var GenKindImpl = class {
|
|
150
150
|
value;
|
|
@@ -266,7 +266,7 @@ var internalCall = isNotOptimizedAway ? standard.effect_internal_function : forc
|
|
|
266
266
|
var genConstructor = function* () {
|
|
267
267
|
}.constructor;
|
|
268
268
|
|
|
269
|
-
// node_modules/.pnpm/effect@3.19.
|
|
269
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Hash.js
|
|
270
270
|
var randomHashCache = /* @__PURE__ */ globalValue(/* @__PURE__ */ Symbol.for("effect/Hash/randomHashCache"), () => /* @__PURE__ */ new WeakMap());
|
|
271
271
|
var symbol = /* @__PURE__ */ Symbol.for("effect/Hash");
|
|
272
272
|
var hash = (self) => {
|
|
@@ -291,6 +291,9 @@ var hash = (self) => {
|
|
|
291
291
|
if (self === null) {
|
|
292
292
|
return string("null");
|
|
293
293
|
} else if (self instanceof Date) {
|
|
294
|
+
if (Number.isNaN(self.getTime())) {
|
|
295
|
+
return string("Invalid Date");
|
|
296
|
+
}
|
|
294
297
|
return hash(self.toISOString());
|
|
295
298
|
} else if (self instanceof URL) {
|
|
296
299
|
return hash(self.href);
|
|
@@ -365,7 +368,7 @@ var cached = function() {
|
|
|
365
368
|
return hash2;
|
|
366
369
|
};
|
|
367
370
|
|
|
368
|
-
// node_modules/.pnpm/effect@3.19.
|
|
371
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Equal.js
|
|
369
372
|
var symbol2 = /* @__PURE__ */ Symbol.for("effect/Equal");
|
|
370
373
|
function equals() {
|
|
371
374
|
if (arguments.length === 1) {
|
|
@@ -390,7 +393,9 @@ function compareBoth(self, that) {
|
|
|
390
393
|
return structuralRegionState.enabled && structuralRegionState.tester ? structuralRegionState.tester(self, that) : false;
|
|
391
394
|
}
|
|
392
395
|
} else if (self instanceof Date && that instanceof Date) {
|
|
393
|
-
|
|
396
|
+
const t1 = self.getTime();
|
|
397
|
+
const t2 = that.getTime();
|
|
398
|
+
return t1 === t2 || Number.isNaN(t1) && Number.isNaN(t2);
|
|
394
399
|
} else if (self instanceof URL && that instanceof URL) {
|
|
395
400
|
return self.href === that.href;
|
|
396
401
|
}
|
|
@@ -419,7 +424,7 @@ function compareBoth(self, that) {
|
|
|
419
424
|
var isEqual = (u) => hasProperty(u, symbol2);
|
|
420
425
|
var equivalence = () => equals;
|
|
421
426
|
|
|
422
|
-
// node_modules/.pnpm/effect@3.19.
|
|
427
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Inspectable.js
|
|
423
428
|
var NodeInspectSymbol = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
|
|
424
429
|
var toJSON = (x) => {
|
|
425
430
|
try {
|
|
@@ -471,7 +476,7 @@ var redact = (u) => {
|
|
|
471
476
|
return u;
|
|
472
477
|
};
|
|
473
478
|
|
|
474
|
-
// node_modules/.pnpm/effect@3.19.
|
|
479
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Pipeable.js
|
|
475
480
|
var pipeArguments = (self, args2) => {
|
|
476
481
|
switch (args2.length) {
|
|
477
482
|
case 0:
|
|
@@ -504,14 +509,14 @@ var pipeArguments = (self, args2) => {
|
|
|
504
509
|
}
|
|
505
510
|
};
|
|
506
511
|
|
|
507
|
-
// node_modules/.pnpm/effect@3.19.
|
|
512
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/opCodes/effect.js
|
|
508
513
|
var OP_COMMIT = "Commit";
|
|
509
514
|
|
|
510
|
-
// node_modules/.pnpm/effect@3.19.
|
|
511
|
-
var moduleVersion = "3.19.
|
|
515
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/version.js
|
|
516
|
+
var moduleVersion = "3.19.13";
|
|
512
517
|
var getCurrentVersion = () => moduleVersion;
|
|
513
518
|
|
|
514
|
-
// node_modules/.pnpm/effect@3.19.
|
|
519
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/effectable.js
|
|
515
520
|
var EffectTypeId = /* @__PURE__ */ Symbol.for("effect/Effect");
|
|
516
521
|
var StreamTypeId = /* @__PURE__ */ Symbol.for("effect/Stream");
|
|
517
522
|
var SinkTypeId = /* @__PURE__ */ Symbol.for("effect/Sink");
|
|
@@ -598,7 +603,7 @@ var StructuralCommitPrototype = {
|
|
|
598
603
|
...StructuralPrototype
|
|
599
604
|
};
|
|
600
605
|
|
|
601
|
-
// node_modules/.pnpm/effect@3.19.
|
|
606
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/option.js
|
|
602
607
|
var TypeId = /* @__PURE__ */ Symbol.for("effect/Option");
|
|
603
608
|
var CommonProto = {
|
|
604
609
|
...EffectPrototype,
|
|
@@ -656,7 +661,7 @@ var some = (value) => {
|
|
|
656
661
|
return a;
|
|
657
662
|
};
|
|
658
663
|
|
|
659
|
-
// node_modules/.pnpm/effect@3.19.
|
|
664
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/either.js
|
|
660
665
|
var TypeId2 = /* @__PURE__ */ Symbol.for("effect/Either");
|
|
661
666
|
var CommonProto2 = {
|
|
662
667
|
...EffectPrototype,
|
|
@@ -718,7 +723,7 @@ var right = (right3) => {
|
|
|
718
723
|
return a;
|
|
719
724
|
};
|
|
720
725
|
|
|
721
|
-
// node_modules/.pnpm/effect@3.19.
|
|
726
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Either.js
|
|
722
727
|
var right2 = right;
|
|
723
728
|
var left2 = left;
|
|
724
729
|
var isLeft2 = isLeft;
|
|
@@ -726,14 +731,14 @@ var isRight2 = isRight;
|
|
|
726
731
|
var map = /* @__PURE__ */ dual(2, (self, f) => isRight2(self) ? right2(f(self.right)) : left2(self.left));
|
|
727
732
|
var getOrElse = /* @__PURE__ */ dual(2, (self, onLeft) => isLeft2(self) ? onLeft(self.left) : self.right);
|
|
728
733
|
|
|
729
|
-
// node_modules/.pnpm/effect@3.19.
|
|
734
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/internal/array.js
|
|
730
735
|
var isNonEmptyArray = (self) => self.length > 0;
|
|
731
736
|
|
|
732
|
-
// node_modules/.pnpm/effect@3.19.
|
|
737
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Order.js
|
|
733
738
|
var make = (compare) => (self, that) => self === that ? 0 : compare(self, that);
|
|
734
739
|
var string2 = /* @__PURE__ */ make((self, that) => self < that ? -1 : 1);
|
|
735
740
|
|
|
736
|
-
// node_modules/.pnpm/effect@3.19.
|
|
741
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Option.js
|
|
737
742
|
var none2 = () => none;
|
|
738
743
|
var some2 = some;
|
|
739
744
|
var isNone2 = isNone;
|
|
@@ -743,7 +748,7 @@ var orElse = /* @__PURE__ */ dual(2, (self, that) => isNone2(self) ? that() : se
|
|
|
743
748
|
var fromNullable = (nullableValue) => nullableValue == null ? none2() : some2(nullableValue);
|
|
744
749
|
var getOrUndefined = /* @__PURE__ */ getOrElse2(constUndefined);
|
|
745
750
|
|
|
746
|
-
// node_modules/.pnpm/effect@3.19.
|
|
751
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Record.js
|
|
747
752
|
var map2 = /* @__PURE__ */ dual(2, (self, f) => {
|
|
748
753
|
const out = {
|
|
749
754
|
...self
|
|
@@ -755,7 +760,7 @@ var map2 = /* @__PURE__ */ dual(2, (self, f) => {
|
|
|
755
760
|
});
|
|
756
761
|
var keys = (self) => Object.keys(self);
|
|
757
762
|
|
|
758
|
-
// node_modules/.pnpm/effect@3.19.
|
|
763
|
+
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Array.js
|
|
759
764
|
var fromIterable = (collection) => Array.isArray(collection) ? collection : Array.from(collection);
|
|
760
765
|
var append = /* @__PURE__ */ dual(2, (self, last) => [...self, last]);
|
|
761
766
|
var appendAll = /* @__PURE__ */ dual(2, (self, that) => fromIterable(self).concat(fromIterable(that)));
|
|
@@ -795,7 +800,10 @@ var containsWith = (isEquivalent) => dual(2, (self, a) => {
|
|
|
795
800
|
var _equivalence = /* @__PURE__ */ equivalence();
|
|
796
801
|
var intersectionWith = (isEquivalent) => {
|
|
797
802
|
const has = containsWith(isEquivalent);
|
|
798
|
-
return dual(2, (self, that) =>
|
|
803
|
+
return dual(2, (self, that) => {
|
|
804
|
+
const bs = fromIterable(that);
|
|
805
|
+
return fromIterable(self).filter((a) => has(bs, a));
|
|
806
|
+
});
|
|
799
807
|
};
|
|
800
808
|
var intersection = /* @__PURE__ */ intersectionWith(_equivalence);
|
|
801
809
|
var empty = () => [];
|
|
@@ -873,12 +881,12 @@ var SingleShotGen2 = class _SingleShotGen {
|
|
|
873
881
|
return new _SingleShotGen(this.self);
|
|
874
882
|
}
|
|
875
883
|
};
|
|
876
|
-
var evaluate = Symbol.for("Nano.evaluate");
|
|
877
|
-
var contA = Symbol.for("Nano.contA");
|
|
878
|
-
var contE = Symbol.for("Nano.contE");
|
|
879
|
-
var contAll = Symbol.for("Nano.contAll");
|
|
880
|
-
var NanoYield = Symbol.for("Nano.yield");
|
|
881
|
-
var args = Symbol.for("Nano.args");
|
|
884
|
+
var evaluate = /* @__PURE__ */ Symbol.for("Nano.evaluate");
|
|
885
|
+
var contA = /* @__PURE__ */ Symbol.for("Nano.contA");
|
|
886
|
+
var contE = /* @__PURE__ */ Symbol.for("Nano.contE");
|
|
887
|
+
var contAll = /* @__PURE__ */ Symbol.for("Nano.contAll");
|
|
888
|
+
var NanoYield = /* @__PURE__ */ Symbol.for("Nano.yield");
|
|
889
|
+
var args = /* @__PURE__ */ Symbol.for("Nano.args");
|
|
882
890
|
var NanoDefectException = class {
|
|
883
891
|
constructor(message, lastSpan) {
|
|
884
892
|
this.message = message;
|
|
@@ -2189,6 +2197,8 @@ var nanoLayer2 = (fa) => pipe(
|
|
|
2189
2197
|
function makeTypeCheckerUtils(ts, typeChecker, tsUtils) {
|
|
2190
2198
|
const readonlyArraySymbol = typeChecker.resolveName("ReadonlyArray", void 0, ts.SymbolFlags.Type, false);
|
|
2191
2199
|
const globalReadonlyArrayType = readonlyArraySymbol ? typeChecker.getDeclaredTypeOfSymbol(readonlyArraySymbol) : void 0;
|
|
2200
|
+
const errorSymbol = typeChecker.resolveName("Error", void 0, ts.SymbolFlags.Type, false);
|
|
2201
|
+
const globalErrorType = errorSymbol ? typeChecker.getDeclaredTypeOfSymbol(errorSymbol) : void 0;
|
|
2192
2202
|
function isUnion(type) {
|
|
2193
2203
|
return !!(type.flags & ts.TypeFlags.Union);
|
|
2194
2204
|
}
|
|
@@ -2437,6 +2447,10 @@ function makeTypeCheckerUtils(ts, typeChecker, tsUtils) {
|
|
|
2437
2447
|
function typeToSimplifiedTypeNode(type, enclosingNode, flags) {
|
|
2438
2448
|
return typeToSimplifiedTypeNodeWorker(type, enclosingNode, flags, 0);
|
|
2439
2449
|
}
|
|
2450
|
+
function isGlobalErrorType(type) {
|
|
2451
|
+
if (!globalErrorType) return false;
|
|
2452
|
+
return typeChecker.isTypeAssignableTo(type, globalErrorType) && typeChecker.isTypeAssignableTo(globalErrorType, type);
|
|
2453
|
+
}
|
|
2440
2454
|
function typeToSimplifiedTypeNodeWorker(type, enclosingNode, flags, depth) {
|
|
2441
2455
|
const fallbackStandard = () => {
|
|
2442
2456
|
const typeNode = typeChecker.typeToTypeNode(type, enclosingNode, flags);
|
|
@@ -2506,6 +2520,15 @@ function makeTypeCheckerUtils(ts, typeChecker, tsUtils) {
|
|
|
2506
2520
|
}
|
|
2507
2521
|
return fallbackStandard();
|
|
2508
2522
|
}
|
|
2523
|
+
function getTypeAtLocation(node) {
|
|
2524
|
+
if (node.parent && ts.isJsxSelfClosingElement(node.parent) && node.parent.tagName === node) return;
|
|
2525
|
+
if (node.parent && ts.isJsxOpeningElement(node.parent) && node.parent.tagName === node) return;
|
|
2526
|
+
if (node.parent && ts.isJsxClosingElement(node.parent) && node.parent.tagName === node) return;
|
|
2527
|
+
if (node.parent && ts.isJsxAttribute(node.parent) && node.parent.name === node) return;
|
|
2528
|
+
if (ts.isExpression(node) || ts.isTypeNode(node)) {
|
|
2529
|
+
return typeChecker.getTypeAtLocation(node);
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2509
2532
|
return {
|
|
2510
2533
|
isUnion,
|
|
2511
2534
|
isReadonlyArrayType,
|
|
@@ -2517,7 +2540,9 @@ function makeTypeCheckerUtils(ts, typeChecker, tsUtils) {
|
|
|
2517
2540
|
deterministicTypeOrder,
|
|
2518
2541
|
getInferredReturnType,
|
|
2519
2542
|
expectedAndRealType,
|
|
2520
|
-
typeToSimplifiedTypeNode
|
|
2543
|
+
typeToSimplifiedTypeNode,
|
|
2544
|
+
isGlobalErrorType,
|
|
2545
|
+
getTypeAtLocation
|
|
2521
2546
|
};
|
|
2522
2547
|
}
|
|
2523
2548
|
|
|
@@ -2639,7 +2664,7 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
2639
2664
|
return isSymbolExportOfPackageModule(symbol3, packageName, memberName, isCorrectSourceFile);
|
|
2640
2665
|
};
|
|
2641
2666
|
const findSymbolsMatchingPackageAndExportedName = (packageName, exportedSymbolName) => cachedBy(
|
|
2642
|
-
fn("TypeParser.findSymbolsMatchingPackageAndExportedName")(function* (
|
|
2667
|
+
fn("TypeParser.findSymbolsMatchingPackageAndExportedName")(function* () {
|
|
2643
2668
|
const result = [];
|
|
2644
2669
|
for (const sourceFile of program.getSourceFiles()) {
|
|
2645
2670
|
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
|
@@ -2653,7 +2678,7 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
2653
2678
|
return result;
|
|
2654
2679
|
}),
|
|
2655
2680
|
`TypeParser.findSymbolsMatchingPackageAndExportedName(${packageName}, ${exportedSymbolName})`,
|
|
2656
|
-
(
|
|
2681
|
+
() => program
|
|
2657
2682
|
);
|
|
2658
2683
|
const isCauseTypeSourceFile = cachedBy(
|
|
2659
2684
|
fn("TypeParser.isCauseTypeSourceFile")(function* (sourceFile) {
|
|
@@ -2668,20 +2693,22 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
2668
2693
|
"TypeParser.isCauseTypeSourceFile",
|
|
2669
2694
|
(sourceFile) => sourceFile
|
|
2670
2695
|
);
|
|
2671
|
-
const
|
|
2672
|
-
fn("TypeParser.
|
|
2673
|
-
const symbols = yield* findSymbolsMatchingPackageAndExportedName("effect", "YieldableError")(
|
|
2674
|
-
const result = [];
|
|
2696
|
+
const extendsCauseYieldableError = cachedBy(
|
|
2697
|
+
fn("TypeParser.extendsCauseYieldableError")(function* (givenType) {
|
|
2698
|
+
const symbols = yield* findSymbolsMatchingPackageAndExportedName("effect", "YieldableError")();
|
|
2675
2699
|
for (const [symbol3, sourceFile] of symbols) {
|
|
2676
|
-
const causeFile = yield* isCauseTypeSourceFile(sourceFile);
|
|
2700
|
+
const causeFile = yield* pipe(isCauseTypeSourceFile(sourceFile), orElse2(() => void_));
|
|
2677
2701
|
if (!causeFile) continue;
|
|
2678
2702
|
const type = typeChecker.getDeclaredTypeOfSymbol(symbol3);
|
|
2679
|
-
|
|
2703
|
+
if (!type) continue;
|
|
2704
|
+
if (typeChecker.isTypeAssignableTo(givenType, type)) {
|
|
2705
|
+
return type;
|
|
2706
|
+
}
|
|
2680
2707
|
}
|
|
2681
|
-
return
|
|
2708
|
+
return yield* typeParserIssue("Type does not extend Cause.YieldableError", givenType);
|
|
2682
2709
|
}),
|
|
2683
|
-
"TypeParser.
|
|
2684
|
-
(
|
|
2710
|
+
"TypeParser.extendsCauseYieldableError",
|
|
2711
|
+
(type) => type
|
|
2685
2712
|
);
|
|
2686
2713
|
function covariantTypeArgument(type) {
|
|
2687
2714
|
const signatures = typeChecker.getSignaturesOfType(type, ts.SignatureKind.Call);
|
|
@@ -3071,7 +3098,8 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
3071
3098
|
}
|
|
3072
3099
|
if (ts.isYieldExpression(nodeToCheck) && nodeToCheck.asteriskToken && nodeToCheck.expression) {
|
|
3073
3100
|
const yieldedExpression = nodeToCheck.expression;
|
|
3074
|
-
const type =
|
|
3101
|
+
const type = typeCheckerUtils.getTypeAtLocation(yieldedExpression);
|
|
3102
|
+
if (!type) continue;
|
|
3075
3103
|
const { A: successType } = yield* effectType(type, yieldedExpression);
|
|
3076
3104
|
let replacementNode = succeed(yieldedExpression);
|
|
3077
3105
|
if (!explicitReturn && !(successType.flags & ts.TypeFlags.VoidLike)) {
|
|
@@ -3662,11 +3690,79 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
3662
3690
|
"TypeParser.extendsEffectService",
|
|
3663
3691
|
(atLocation) => atLocation
|
|
3664
3692
|
);
|
|
3693
|
+
const isEffectSqlModelTypeSourceFile = cachedBy(
|
|
3694
|
+
fn("TypeParser.isEffectSqlModelTypeSourceFile")(function* (sourceFile) {
|
|
3695
|
+
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
|
3696
|
+
if (!moduleSymbol) return yield* typeParserIssue("Node has no symbol", void 0, sourceFile);
|
|
3697
|
+
const classSymbol = typeChecker.tryGetMemberInModuleExports("Class", moduleSymbol);
|
|
3698
|
+
if (!classSymbol) return yield* typeParserIssue("Model's Class type not found", void 0, sourceFile);
|
|
3699
|
+
const makeRepositorySymbol = typeChecker.tryGetMemberInModuleExports("makeRepository", moduleSymbol);
|
|
3700
|
+
if (!makeRepositorySymbol) {
|
|
3701
|
+
return yield* typeParserIssue("Model's makeRepository type not found", void 0, sourceFile);
|
|
3702
|
+
}
|
|
3703
|
+
const makeDataLoadersSymbol = typeChecker.tryGetMemberInModuleExports("makeDataLoaders", moduleSymbol);
|
|
3704
|
+
if (!makeDataLoadersSymbol) {
|
|
3705
|
+
return yield* typeParserIssue("Model's makeDataLoaders type not found", void 0, sourceFile);
|
|
3706
|
+
}
|
|
3707
|
+
return sourceFile;
|
|
3708
|
+
}),
|
|
3709
|
+
"TypeParser.isEffectSqlModelTypeSourceFile",
|
|
3710
|
+
(sourceFile) => sourceFile
|
|
3711
|
+
);
|
|
3712
|
+
const isNodeReferenceToEffectSqlModelModuleApi = (memberName) => cachedBy(
|
|
3713
|
+
fn("TypeParser.isNodeReferenceToEffectSqlModelModuleApi")(function* (node) {
|
|
3714
|
+
return yield* isNodeReferenceToExportOfPackageModule(
|
|
3715
|
+
node,
|
|
3716
|
+
"@effect/sql",
|
|
3717
|
+
isEffectSqlModelTypeSourceFile,
|
|
3718
|
+
memberName
|
|
3719
|
+
);
|
|
3720
|
+
}),
|
|
3721
|
+
`TypeParser.isNodeReferenceToEffectSqlModelModuleApi(${memberName})`,
|
|
3722
|
+
(node) => node
|
|
3723
|
+
);
|
|
3724
|
+
const extendsEffectSqlModelClass = cachedBy(
|
|
3725
|
+
fn("TypeParser.extendsEffectSqlModelClass")(function* (atLocation) {
|
|
3726
|
+
if (!atLocation.name) {
|
|
3727
|
+
return yield* typeParserIssue("Class has no name", void 0, atLocation);
|
|
3728
|
+
}
|
|
3729
|
+
const heritageClauses = atLocation.heritageClauses;
|
|
3730
|
+
if (!heritageClauses) {
|
|
3731
|
+
return yield* typeParserIssue("Class has no heritage clauses", void 0, atLocation);
|
|
3732
|
+
}
|
|
3733
|
+
for (const heritageClause of heritageClauses) {
|
|
3734
|
+
for (const typeX of heritageClause.types) {
|
|
3735
|
+
if (ts.isExpressionWithTypeArguments(typeX)) {
|
|
3736
|
+
const expression = typeX.expression;
|
|
3737
|
+
if (ts.isCallExpression(expression)) {
|
|
3738
|
+
const schemaCall = expression.expression;
|
|
3739
|
+
if (ts.isCallExpression(schemaCall) && schemaCall.typeArguments && schemaCall.typeArguments.length > 0) {
|
|
3740
|
+
const isEffectSchemaModuleApi = yield* pipe(
|
|
3741
|
+
isNodeReferenceToEffectSqlModelModuleApi("Class")(schemaCall.expression),
|
|
3742
|
+
option
|
|
3743
|
+
);
|
|
3744
|
+
if (isSome2(isEffectSchemaModuleApi)) {
|
|
3745
|
+
return {
|
|
3746
|
+
className: atLocation.name,
|
|
3747
|
+
selfTypeNode: schemaCall.typeArguments[0]
|
|
3748
|
+
};
|
|
3749
|
+
}
|
|
3750
|
+
}
|
|
3751
|
+
}
|
|
3752
|
+
}
|
|
3753
|
+
}
|
|
3754
|
+
}
|
|
3755
|
+
return yield* typeParserIssue("Class does not extend @effect/sql's Model.Class", void 0, atLocation);
|
|
3756
|
+
}),
|
|
3757
|
+
"TypeParser.extendsEffectSqlModelClass",
|
|
3758
|
+
(atLocation) => atLocation
|
|
3759
|
+
);
|
|
3665
3760
|
return {
|
|
3666
3761
|
isNodeReferenceToEffectModuleApi,
|
|
3667
3762
|
isNodeReferenceToEffectSchemaModuleApi,
|
|
3668
3763
|
isNodeReferenceToEffectDataModuleApi,
|
|
3669
3764
|
isNodeReferenceToEffectContextModuleApi,
|
|
3765
|
+
isNodeReferenceToEffectSqlModelModuleApi,
|
|
3670
3766
|
effectType,
|
|
3671
3767
|
strictEffectType,
|
|
3672
3768
|
layerType,
|
|
@@ -3676,7 +3772,7 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
3676
3772
|
effectGen,
|
|
3677
3773
|
effectFnUntracedGen,
|
|
3678
3774
|
effectFnGen,
|
|
3679
|
-
|
|
3775
|
+
extendsCauseYieldableError,
|
|
3680
3776
|
unnecessaryEffectGen: unnecessaryEffectGen2,
|
|
3681
3777
|
effectSchemaType,
|
|
3682
3778
|
contextTag,
|
|
@@ -3692,7 +3788,8 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
3692
3788
|
extendsSchemaTaggedError,
|
|
3693
3789
|
extendsDataTaggedError,
|
|
3694
3790
|
extendsDataTaggedClass,
|
|
3695
|
-
extendsSchemaTaggedRequest
|
|
3791
|
+
extendsSchemaTaggedRequest,
|
|
3792
|
+
extendsEffectSqlModelClass
|
|
3696
3793
|
};
|
|
3697
3794
|
}
|
|
3698
3795
|
|
|
@@ -3700,10 +3797,12 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
3700
3797
|
var anyUnknownInErrorContext = createDiagnostic({
|
|
3701
3798
|
name: "anyUnknownInErrorContext",
|
|
3702
3799
|
code: 28,
|
|
3800
|
+
description: "Detects 'any' or 'unknown' types in Effect error or requirements channels",
|
|
3703
3801
|
severity: "off",
|
|
3704
3802
|
apply: fn("anyUnknownInErrorContext.apply")(function* (sourceFile, report) {
|
|
3705
3803
|
const ts = yield* service(TypeScriptApi);
|
|
3706
3804
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
3805
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
3707
3806
|
const typeParser = yield* service(TypeParser);
|
|
3708
3807
|
const isAnyOrUnknown = (type) => (type.flags & ts.TypeFlags.Any) > 0 || (type.flags & ts.TypeFlags.Unknown) > 0;
|
|
3709
3808
|
const matchingNodes = [];
|
|
@@ -3723,7 +3822,8 @@ var anyUnknownInErrorContext = createDiagnostic({
|
|
|
3723
3822
|
if (ts.isParameter(node) || ts.isPropertyDeclaration(node) || ts.isVariableDeclaration(node)) {
|
|
3724
3823
|
if (node.type) {
|
|
3725
3824
|
const typeNode = node.type;
|
|
3726
|
-
const type2 =
|
|
3825
|
+
const type2 = typeCheckerUtils.getTypeAtLocation(node.type);
|
|
3826
|
+
if (!type2) continue;
|
|
3727
3827
|
const expectedEffect = yield* pipe(
|
|
3728
3828
|
typeParser.strictEffectType(type2, node.type),
|
|
3729
3829
|
orElse2(() => typeParser.layerType(type2, typeNode)),
|
|
@@ -3734,11 +3834,7 @@ var anyUnknownInErrorContext = createDiagnostic({
|
|
|
3734
3834
|
}
|
|
3735
3835
|
ts.forEachChild(node, appendNodeToVisit);
|
|
3736
3836
|
if (!ts.isExpression(node)) continue;
|
|
3737
|
-
|
|
3738
|
-
if (node.parent && ts.isJsxOpeningElement(node.parent) && node.parent.tagName === node) continue;
|
|
3739
|
-
if (node.parent && ts.isJsxClosingElement(node.parent) && node.parent.tagName === node) continue;
|
|
3740
|
-
if (node.parent && ts.isJsxAttribute(node.parent) && node.parent.name === node) continue;
|
|
3741
|
-
let type = typeChecker.getTypeAtLocation(node);
|
|
3837
|
+
let type = typeCheckerUtils.getTypeAtLocation(node);
|
|
3742
3838
|
if (ts.isCallExpression(node)) {
|
|
3743
3839
|
const resolvedSignature = typeChecker.getResolvedSignature(node);
|
|
3744
3840
|
if (resolvedSignature) {
|
|
@@ -3804,11 +3900,13 @@ var anyUnknownInErrorContext = createDiagnostic({
|
|
|
3804
3900
|
var catchUnfailableEffect = createDiagnostic({
|
|
3805
3901
|
name: "catchUnfailableEffect",
|
|
3806
3902
|
code: 2,
|
|
3903
|
+
description: "Warns when using error handling on Effects that never fail (error type is 'never')",
|
|
3807
3904
|
severity: "suggestion",
|
|
3808
3905
|
apply: fn("catchUnfailableEffect.apply")(function* (sourceFile, report) {
|
|
3809
3906
|
const ts = yield* service(TypeScriptApi);
|
|
3810
3907
|
const typeParser = yield* service(TypeParser);
|
|
3811
3908
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
3909
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
3812
3910
|
const nodeToVisit = [];
|
|
3813
3911
|
const appendNodeToVisit = (node) => {
|
|
3814
3912
|
nodeToVisit.push(node);
|
|
@@ -3839,7 +3937,7 @@ var catchUnfailableEffect = createDiagnostic({
|
|
|
3839
3937
|
if (argIndex !== -1) {
|
|
3840
3938
|
let effectTypeToCheck;
|
|
3841
3939
|
if (argIndex === 0) {
|
|
3842
|
-
effectTypeToCheck =
|
|
3940
|
+
effectTypeToCheck = typeCheckerUtils.getTypeAtLocation(subject);
|
|
3843
3941
|
} else {
|
|
3844
3942
|
const signature = typeChecker.getResolvedSignature(pipeCallNode);
|
|
3845
3943
|
if (signature) {
|
|
@@ -3878,6 +3976,7 @@ var catchUnfailableEffect = createDiagnostic({
|
|
|
3878
3976
|
var classSelfMismatch = createDiagnostic({
|
|
3879
3977
|
name: "classSelfMismatch",
|
|
3880
3978
|
code: 20,
|
|
3979
|
+
description: "Ensures Self type parameter matches the class name in Service/Tag/Schema classes",
|
|
3881
3980
|
severity: "error",
|
|
3882
3981
|
apply: fn("classSelfMismatch.apply")(function* (sourceFile, report) {
|
|
3883
3982
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -3899,6 +3998,7 @@ var classSelfMismatch = createDiagnostic({
|
|
|
3899
3998
|
orElse2(() => typeParser.extendsSchemaTaggedClass(node)),
|
|
3900
3999
|
orElse2(() => typeParser.extendsSchemaTaggedError(node)),
|
|
3901
4000
|
orElse2(() => typeParser.extendsSchemaTaggedRequest(node)),
|
|
4001
|
+
orElse2(() => typeParser.extendsEffectSqlModelClass(node)),
|
|
3902
4002
|
orElse2(() => void_)
|
|
3903
4003
|
);
|
|
3904
4004
|
if (result) {
|
|
@@ -4008,6 +4108,7 @@ function createString(sourceFile, identifier, kind) {
|
|
|
4008
4108
|
var deterministicKeys = createDiagnostic({
|
|
4009
4109
|
name: "deterministicKeys",
|
|
4010
4110
|
code: 25,
|
|
4111
|
+
description: "Enforces deterministic naming for service/tag/error identifiers based on class names",
|
|
4011
4112
|
severity: "off",
|
|
4012
4113
|
apply: fn("deterministicKeys.apply")(function* (sourceFile, report) {
|
|
4013
4114
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -4128,6 +4229,7 @@ var programResolvedCacheSize = /* @__PURE__ */ new Map();
|
|
|
4128
4229
|
var duplicatePackage = createDiagnostic({
|
|
4129
4230
|
name: "duplicatePackage",
|
|
4130
4231
|
code: 6,
|
|
4232
|
+
description: "Detects when multiple versions of the same Effect package are loaded",
|
|
4131
4233
|
severity: "warning",
|
|
4132
4234
|
apply: fn("duplicatePackage.apply")(function* (sourceFile, report) {
|
|
4133
4235
|
const program = yield* service(TypeScriptProgram);
|
|
@@ -4175,6 +4277,7 @@ ${versions.map((version) => `- found ${version} at ${resolvedPackages[packageNam
|
|
|
4175
4277
|
var effectGenUsesAdapter = createDiagnostic({
|
|
4176
4278
|
name: "effectGenUsesAdapter",
|
|
4177
4279
|
code: 23,
|
|
4280
|
+
description: "Warns when using the deprecated adapter parameter in Effect.gen",
|
|
4178
4281
|
severity: "warning",
|
|
4179
4282
|
apply: fn("effectGenUsesAdapter.apply")(function* (sourceFile, report) {
|
|
4180
4283
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -4212,6 +4315,7 @@ var effectGenUsesAdapter = createDiagnostic({
|
|
|
4212
4315
|
var effectInVoidSuccess = createDiagnostic({
|
|
4213
4316
|
name: "effectInVoidSuccess",
|
|
4214
4317
|
code: 14,
|
|
4318
|
+
description: "Detects nested Effects in void success channels that may cause unexecuted effects",
|
|
4215
4319
|
severity: "warning",
|
|
4216
4320
|
apply: fn("effectInVoidSuccess.apply")(function* (sourceFile, report) {
|
|
4217
4321
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -4260,10 +4364,12 @@ var effectInVoidSuccess = createDiagnostic({
|
|
|
4260
4364
|
var floatingEffect = createDiagnostic({
|
|
4261
4365
|
name: "floatingEffect",
|
|
4262
4366
|
code: 3,
|
|
4367
|
+
description: "Ensures Effects are yielded or assigned to variables, not left floating",
|
|
4263
4368
|
severity: "error",
|
|
4264
4369
|
apply: fn("floatingEffect.apply")(function* (sourceFile, report) {
|
|
4265
4370
|
const ts = yield* service(TypeScriptApi);
|
|
4266
4371
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
4372
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
4267
4373
|
const typeParser = yield* service(TypeParser);
|
|
4268
4374
|
function isFloatingExpression(node) {
|
|
4269
4375
|
if (!ts.isExpressionStatement(node)) return false;
|
|
@@ -4282,7 +4388,8 @@ var floatingEffect = createDiagnostic({
|
|
|
4282
4388
|
const node = nodeToVisit.shift();
|
|
4283
4389
|
ts.forEachChild(node, appendNodeToVisit);
|
|
4284
4390
|
if (!isFloatingExpression(node)) continue;
|
|
4285
|
-
const type =
|
|
4391
|
+
const type = typeCheckerUtils.getTypeAtLocation(node.expression);
|
|
4392
|
+
if (!type) continue;
|
|
4286
4393
|
const effect = yield* option(typeParser.effectType(type, node.expression));
|
|
4287
4394
|
if (isSome2(effect)) {
|
|
4288
4395
|
const allowedFloatingEffects = yield* pipe(
|
|
@@ -4308,6 +4415,7 @@ var floatingEffect = createDiagnostic({
|
|
|
4308
4415
|
var genericEffectServices = createDiagnostic({
|
|
4309
4416
|
name: "genericEffectServices",
|
|
4310
4417
|
code: 10,
|
|
4418
|
+
description: "Prevents services with type parameters that cannot be discriminated at runtime",
|
|
4311
4419
|
severity: "warning",
|
|
4312
4420
|
apply: fn("genericEffectServices.apply")(function* (sourceFile, report) {
|
|
4313
4421
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -4350,10 +4458,56 @@ var genericEffectServices = createDiagnostic({
|
|
|
4350
4458
|
})
|
|
4351
4459
|
});
|
|
4352
4460
|
|
|
4461
|
+
// src/diagnostics/globalErrorInEffectFailure.ts
|
|
4462
|
+
var globalErrorInEffectFailure = createDiagnostic({
|
|
4463
|
+
name: "globalErrorInEffectFailure",
|
|
4464
|
+
code: 35,
|
|
4465
|
+
description: "Warns when Effect.fail is called with the global Error type",
|
|
4466
|
+
severity: "warning",
|
|
4467
|
+
apply: fn("globalErrorInEffectFailure.apply")(function* (sourceFile, report) {
|
|
4468
|
+
const ts = yield* service(TypeScriptApi);
|
|
4469
|
+
const typeParser = yield* service(TypeParser);
|
|
4470
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
4471
|
+
const nodeToVisit = [];
|
|
4472
|
+
const appendNodeToVisit = (node) => {
|
|
4473
|
+
nodeToVisit.push(node);
|
|
4474
|
+
return void 0;
|
|
4475
|
+
};
|
|
4476
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
4477
|
+
while (nodeToVisit.length > 0) {
|
|
4478
|
+
const node = nodeToVisit.shift();
|
|
4479
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
4480
|
+
if (ts.isCallExpression(node)) {
|
|
4481
|
+
yield* pipe(
|
|
4482
|
+
typeParser.isNodeReferenceToEffectModuleApi("fail")(node.expression),
|
|
4483
|
+
flatMap2(() => {
|
|
4484
|
+
if (node.arguments.length > 0) {
|
|
4485
|
+
const failArgument = node.arguments[0];
|
|
4486
|
+
const argumentType = typeCheckerUtils.getTypeAtLocation(failArgument);
|
|
4487
|
+
if (argumentType && typeCheckerUtils.isGlobalErrorType(argumentType)) {
|
|
4488
|
+
return sync(
|
|
4489
|
+
() => report({
|
|
4490
|
+
location: node,
|
|
4491
|
+
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.`,
|
|
4492
|
+
fixes: []
|
|
4493
|
+
})
|
|
4494
|
+
);
|
|
4495
|
+
}
|
|
4496
|
+
}
|
|
4497
|
+
return void_;
|
|
4498
|
+
}),
|
|
4499
|
+
ignore
|
|
4500
|
+
);
|
|
4501
|
+
}
|
|
4502
|
+
}
|
|
4503
|
+
})
|
|
4504
|
+
});
|
|
4505
|
+
|
|
4353
4506
|
// src/diagnostics/importFromBarrel.ts
|
|
4354
4507
|
var importFromBarrel = createDiagnostic({
|
|
4355
4508
|
name: "importFromBarrel",
|
|
4356
4509
|
code: 12,
|
|
4510
|
+
description: "Suggests importing from specific module paths instead of barrel exports",
|
|
4357
4511
|
severity: "off",
|
|
4358
4512
|
apply: fn("importFromBarrel.apply")(function* (sourceFile, report) {
|
|
4359
4513
|
const languageServicePluginOptions = yield* service(LanguageServicePluginOptions);
|
|
@@ -4493,6 +4647,7 @@ var importFromBarrel = createDiagnostic({
|
|
|
4493
4647
|
var leakingRequirements = createDiagnostic({
|
|
4494
4648
|
name: "leakingRequirements",
|
|
4495
4649
|
code: 8,
|
|
4650
|
+
description: "Detects implementation services leaked in service methods",
|
|
4496
4651
|
severity: "suggestion",
|
|
4497
4652
|
apply: fn("leakingRequirements.apply")(function* (sourceFile, report) {
|
|
4498
4653
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -4600,7 +4755,8 @@ More info at https://effect.website/docs/requirements-management/layers/#avoidin
|
|
|
4600
4755
|
const node = nodeToVisit.shift();
|
|
4601
4756
|
const typesToCheck = [];
|
|
4602
4757
|
if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.isIdentifier(node.expression.name) && ts.idText(node.expression.name) === "GenericTag") {
|
|
4603
|
-
|
|
4758
|
+
const nodeType = typeCheckerUtils.getTypeAtLocation(node);
|
|
4759
|
+
if (nodeType) typesToCheck.push([nodeType, node]);
|
|
4604
4760
|
} else if (ts.isClassDeclaration(node) && node.name && node.heritageClauses) {
|
|
4605
4761
|
const classSym = typeChecker.getSymbolAtLocation(node.name);
|
|
4606
4762
|
if (classSym) {
|
|
@@ -4634,10 +4790,12 @@ More info at https://effect.website/docs/requirements-management/layers/#avoidin
|
|
|
4634
4790
|
var missedPipeableOpportunity = createDiagnostic({
|
|
4635
4791
|
name: "missedPipeableOpportunity",
|
|
4636
4792
|
code: 26,
|
|
4793
|
+
description: "Enforces the use of pipeable style for nested function calls",
|
|
4637
4794
|
severity: "off",
|
|
4638
4795
|
apply: fn("missedPipeableOpportunity.apply")(function* (sourceFile, report) {
|
|
4639
4796
|
const ts = yield* service(TypeScriptApi);
|
|
4640
4797
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
4798
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
4641
4799
|
const typeParser = yield* service(TypeParser);
|
|
4642
4800
|
const options = yield* service(LanguageServicePluginOptions);
|
|
4643
4801
|
const nodeToVisit = [sourceFile];
|
|
@@ -4668,7 +4826,8 @@ var missedPipeableOpportunity = createDiagnostic({
|
|
|
4668
4826
|
const originalParentChain = parentChain.slice();
|
|
4669
4827
|
while (parentChain.length > options.pipeableMinArgCount) {
|
|
4670
4828
|
const subject = parentChain.pop();
|
|
4671
|
-
const resultType =
|
|
4829
|
+
const resultType = typeCheckerUtils.getTypeAtLocation(subject);
|
|
4830
|
+
if (!resultType) continue;
|
|
4672
4831
|
const pipeableType = yield* pipe(typeParser.pipeableType(resultType, subject), orElse2(() => void_));
|
|
4673
4832
|
if (pipeableType) {
|
|
4674
4833
|
report({
|
|
@@ -4713,6 +4872,7 @@ var missedPipeableOpportunity = createDiagnostic({
|
|
|
4713
4872
|
var missingEffectContext = createDiagnostic({
|
|
4714
4873
|
name: "missingEffectContext",
|
|
4715
4874
|
code: 1,
|
|
4875
|
+
description: "Reports missing service requirements in Effect context channel",
|
|
4716
4876
|
severity: "error",
|
|
4717
4877
|
apply: fn("missingEffectContext.apply")(function* (sourceFile, report) {
|
|
4718
4878
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
@@ -4761,6 +4921,7 @@ var missingEffectContext = createDiagnostic({
|
|
|
4761
4921
|
var missingEffectError = createDiagnostic({
|
|
4762
4922
|
name: "missingEffectError",
|
|
4763
4923
|
code: 1,
|
|
4924
|
+
description: "Reports missing error types in Effect error channel",
|
|
4764
4925
|
severity: "error",
|
|
4765
4926
|
apply: fn("missingEffectError.apply")(function* (sourceFile, report) {
|
|
4766
4927
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -4900,6 +5061,7 @@ var missingEffectError = createDiagnostic({
|
|
|
4900
5061
|
var missingEffectServiceDependency = createDiagnostic({
|
|
4901
5062
|
name: "missingEffectServiceDependency",
|
|
4902
5063
|
code: 22,
|
|
5064
|
+
description: "Checks that Effect.Service dependencies satisfy all required layer inputs",
|
|
4903
5065
|
severity: "off",
|
|
4904
5066
|
apply: fn("missingEffectServiceDependency.apply")(function* (sourceFile, report) {
|
|
4905
5067
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -4941,13 +5103,15 @@ var missingEffectServiceDependency = createDiagnostic({
|
|
|
4941
5103
|
excludeNever
|
|
4942
5104
|
);
|
|
4943
5105
|
const providedIndexes = /* @__PURE__ */ new Set();
|
|
4944
|
-
const optionsType = typeChecker.getTypeAtLocation(options);
|
|
4945
|
-
const dependenciesProperty = typeChecker.getPropertyOfType(optionsType, "dependencies");
|
|
4946
5106
|
let types = [];
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
const
|
|
4950
|
-
|
|
5107
|
+
const optionsType = typeCheckerUtils.getTypeAtLocation(options);
|
|
5108
|
+
if (optionsType) {
|
|
5109
|
+
const dependenciesProperty = typeChecker.getPropertyOfType(optionsType, "dependencies");
|
|
5110
|
+
if (dependenciesProperty) {
|
|
5111
|
+
const dependenciesTypes = typeChecker.getTypeOfSymbolAtLocation(dependenciesProperty, options);
|
|
5112
|
+
const numberIndexType = typeChecker.getIndexTypeOfType(dependenciesTypes, ts.IndexKind.Number);
|
|
5113
|
+
types = numberIndexType ? typeCheckerUtils.unrollUnionMembers(numberIndexType) : [];
|
|
5114
|
+
}
|
|
4951
5115
|
}
|
|
4952
5116
|
for (const depType of types) {
|
|
4953
5117
|
const depLayerResult = yield* pipe(
|
|
@@ -4990,10 +5154,11 @@ var missingEffectServiceDependency = createDiagnostic({
|
|
|
4990
5154
|
var missingReturnYieldStar = createDiagnostic({
|
|
4991
5155
|
name: "missingReturnYieldStar",
|
|
4992
5156
|
code: 7,
|
|
5157
|
+
description: "Suggests using 'return yield*' for Effects with never success for better type narrowing",
|
|
4993
5158
|
severity: "error",
|
|
4994
5159
|
apply: fn("missingReturnYieldStar.apply")(function* (sourceFile, report) {
|
|
4995
5160
|
const ts = yield* service(TypeScriptApi);
|
|
4996
|
-
const
|
|
5161
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
4997
5162
|
const typeParser = yield* service(TypeParser);
|
|
4998
5163
|
const nodeToVisit = [];
|
|
4999
5164
|
const appendNodeToVisit = (node) => {
|
|
@@ -5005,42 +5170,44 @@ var missingReturnYieldStar = createDiagnostic({
|
|
|
5005
5170
|
const node = nodeToVisit.shift();
|
|
5006
5171
|
ts.forEachChild(node, appendNodeToVisit);
|
|
5007
5172
|
if (ts.isYieldExpression(node) && node.expression && node.asteriskToken) {
|
|
5008
|
-
const type =
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
if (generatorFunctionOrReturnStatement && generatorFunctionOrReturnStatement.
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5173
|
+
const type = typeCheckerUtils.getTypeAtLocation(node.expression);
|
|
5174
|
+
if (type) {
|
|
5175
|
+
const maybeEffect = yield* option(typeParser.effectType(type, node.expression));
|
|
5176
|
+
if (isSome2(maybeEffect) && maybeEffect.value.A.flags & ts.TypeFlags.Never) {
|
|
5177
|
+
const generatorFunctionOrReturnStatement = ts.findAncestor(
|
|
5178
|
+
node,
|
|
5179
|
+
(_) => ts.isFunctionExpression(_) || ts.isFunctionDeclaration(_) || ts.isMethodDeclaration(_) || ts.isReturnStatement(_) || ts.isThrowStatement(_)
|
|
5180
|
+
);
|
|
5181
|
+
if (generatorFunctionOrReturnStatement && !ts.isReturnStatement(generatorFunctionOrReturnStatement) && !ts.isThrowStatement(generatorFunctionOrReturnStatement)) {
|
|
5182
|
+
if (generatorFunctionOrReturnStatement && generatorFunctionOrReturnStatement.parent) {
|
|
5183
|
+
const effectGenNode = generatorFunctionOrReturnStatement.parent;
|
|
5184
|
+
const effectGenLike = yield* pipe(
|
|
5185
|
+
typeParser.effectGen(effectGenNode),
|
|
5186
|
+
orElse2(() => typeParser.effectFnUntracedGen(effectGenNode)),
|
|
5187
|
+
orElse2(() => typeParser.effectFnGen(effectGenNode)),
|
|
5188
|
+
option
|
|
5189
|
+
);
|
|
5190
|
+
if (isSome2(effectGenLike)) {
|
|
5191
|
+
const fix = node.expression ? [{
|
|
5192
|
+
fixName: "missingReturnYieldStar_fix",
|
|
5193
|
+
description: "Add return statement",
|
|
5194
|
+
apply: gen(function* () {
|
|
5195
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
5196
|
+
changeTracker.replaceNode(
|
|
5197
|
+
sourceFile,
|
|
5198
|
+
node,
|
|
5199
|
+
ts.factory.createReturnStatement(
|
|
5200
|
+
node
|
|
5201
|
+
)
|
|
5202
|
+
);
|
|
5203
|
+
})
|
|
5204
|
+
}] : [];
|
|
5205
|
+
report({
|
|
5206
|
+
location: node,
|
|
5207
|
+
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.`,
|
|
5208
|
+
fixes: fix
|
|
5209
|
+
});
|
|
5210
|
+
}
|
|
5044
5211
|
}
|
|
5045
5212
|
}
|
|
5046
5213
|
}
|
|
@@ -5054,6 +5221,7 @@ var missingReturnYieldStar = createDiagnostic({
|
|
|
5054
5221
|
var missingStarInYieldEffectGen = createDiagnostic({
|
|
5055
5222
|
name: "missingStarInYieldEffectGen",
|
|
5056
5223
|
code: 4,
|
|
5224
|
+
description: "Enforces using 'yield*' instead of 'yield' when yielding Effects in generators",
|
|
5057
5225
|
severity: "error",
|
|
5058
5226
|
apply: fn("missingStarInYieldEffectGen.apply")(function* (sourceFile, report) {
|
|
5059
5227
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -5128,11 +5296,12 @@ var missingStarInYieldEffectGen = createDiagnostic({
|
|
|
5128
5296
|
var multipleEffectProvide = createDiagnostic({
|
|
5129
5297
|
name: "multipleEffectProvide",
|
|
5130
5298
|
code: 18,
|
|
5299
|
+
description: "Warns against chaining Effect.provide calls which can cause service lifecycle issues",
|
|
5131
5300
|
severity: "warning",
|
|
5132
5301
|
apply: fn("multipleEffectProvide.apply")(function* (sourceFile, report) {
|
|
5133
5302
|
const ts = yield* service(TypeScriptApi);
|
|
5134
5303
|
const tsUtils = yield* service(TypeScriptUtils);
|
|
5135
|
-
const
|
|
5304
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
5136
5305
|
const typeParser = yield* service(TypeParser);
|
|
5137
5306
|
const effectModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
|
|
5138
5307
|
sourceFile,
|
|
@@ -5147,7 +5316,8 @@ var multipleEffectProvide = createDiagnostic({
|
|
|
5147
5316
|
const parseEffectProvideLayer = (node) => {
|
|
5148
5317
|
if (ts.isCallExpression(node) && node.arguments.length > 0) {
|
|
5149
5318
|
const layer = node.arguments[0];
|
|
5150
|
-
const type =
|
|
5319
|
+
const type = typeCheckerUtils.getTypeAtLocation(layer);
|
|
5320
|
+
if (!type) return void_;
|
|
5151
5321
|
return pipe(
|
|
5152
5322
|
typeParser.isNodeReferenceToEffectModuleApi("provide")(node.expression),
|
|
5153
5323
|
flatMap2(() => typeParser.layerType(type, layer)),
|
|
@@ -5225,6 +5395,7 @@ var multipleEffectProvide = createDiagnostic({
|
|
|
5225
5395
|
var nonObjectEffectServiceType = createDiagnostic({
|
|
5226
5396
|
name: "nonObjectEffectServiceType",
|
|
5227
5397
|
code: 24,
|
|
5398
|
+
description: "Ensures Effect.Service types are objects, not primitives",
|
|
5228
5399
|
severity: "error",
|
|
5229
5400
|
apply: fn("nonObjectEffectServiceType.apply")(function* (sourceFile, report) {
|
|
5230
5401
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -5263,12 +5434,13 @@ var nonObjectEffectServiceType = createDiagnostic({
|
|
|
5263
5434
|
fixes: []
|
|
5264
5435
|
};
|
|
5265
5436
|
if (propertyName === "succeed") {
|
|
5266
|
-
const valueType =
|
|
5267
|
-
if (isPrimitiveType(valueType)) {
|
|
5437
|
+
const valueType = typeCheckerUtils.getTypeAtLocation(propertyValue);
|
|
5438
|
+
if (valueType && isPrimitiveType(valueType)) {
|
|
5268
5439
|
report(errorToReport);
|
|
5269
5440
|
}
|
|
5270
5441
|
} else if (propertyName === "sync") {
|
|
5271
|
-
const valueType =
|
|
5442
|
+
const valueType = typeCheckerUtils.getTypeAtLocation(propertyValue);
|
|
5443
|
+
if (!valueType) continue;
|
|
5272
5444
|
const signatures = typeChecker.getSignaturesOfType(valueType, ts.SignatureKind.Call);
|
|
5273
5445
|
for (const signature of signatures) {
|
|
5274
5446
|
const returnType = typeChecker.getReturnTypeOfSignature(signature);
|
|
@@ -5278,7 +5450,8 @@ var nonObjectEffectServiceType = createDiagnostic({
|
|
|
5278
5450
|
}
|
|
5279
5451
|
}
|
|
5280
5452
|
} else if (propertyName === "effect" || propertyName === "scoped") {
|
|
5281
|
-
const valueType =
|
|
5453
|
+
const valueType = typeCheckerUtils.getTypeAtLocation(propertyValue);
|
|
5454
|
+
if (!valueType) continue;
|
|
5282
5455
|
const effectResult = yield* pipe(
|
|
5283
5456
|
typeParser.effectType(valueType, propertyValue),
|
|
5284
5457
|
orElse2(() => void_)
|
|
@@ -5625,7 +5798,8 @@ var annotate = createCodegen({
|
|
|
5625
5798
|
}
|
|
5626
5799
|
for (const variableDeclaration of variableDeclarations) {
|
|
5627
5800
|
if (!variableDeclaration.initializer) continue;
|
|
5628
|
-
const initializerType =
|
|
5801
|
+
const initializerType = typeCheckerUtils.getTypeAtLocation(variableDeclaration.initializer);
|
|
5802
|
+
if (!initializerType) continue;
|
|
5629
5803
|
const enclosingNode = ts.findAncestor(variableDeclaration, (_) => tsUtils.isDeclarationKind(_.kind)) || sourceFile;
|
|
5630
5804
|
const initializerTypeNode = fromNullable(typeCheckerUtils.typeToSimplifiedTypeNode(
|
|
5631
5805
|
initializerType,
|
|
@@ -6077,7 +6251,7 @@ var findNodeToProcess = fn("StructuralSchemaGen.findNodeToProcess")(
|
|
|
6077
6251
|
function* (sourceFile, textRange) {
|
|
6078
6252
|
const ts = yield* service(TypeScriptApi);
|
|
6079
6253
|
const tsUtils = yield* service(TypeScriptUtils);
|
|
6080
|
-
const
|
|
6254
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
6081
6255
|
return pipe(
|
|
6082
6256
|
tsUtils.getAncestorNodesInRange(sourceFile, textRange),
|
|
6083
6257
|
filter((node) => ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node)),
|
|
@@ -6086,7 +6260,7 @@ var findNodeToProcess = fn("StructuralSchemaGen.findNodeToProcess")(
|
|
|
6086
6260
|
map3((node) => ({
|
|
6087
6261
|
node,
|
|
6088
6262
|
identifier: node.name,
|
|
6089
|
-
type:
|
|
6263
|
+
type: typeCheckerUtils.getTypeAtLocation(node.name),
|
|
6090
6264
|
isExported: node.modifiers ? (ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export) !== 0 : false
|
|
6091
6265
|
})),
|
|
6092
6266
|
filter(({ type }) => !!type),
|
|
@@ -6264,7 +6438,7 @@ var typeToSchema = createCodegen({
|
|
|
6264
6438
|
)
|
|
6265
6439
|
);
|
|
6266
6440
|
}
|
|
6267
|
-
const type =
|
|
6441
|
+
const type = typeCheckerUtils.getTypeAtLocation(node.name);
|
|
6268
6442
|
if (!type) {
|
|
6269
6443
|
return yield* fail(
|
|
6270
6444
|
new CodegenNotApplicableError(
|
|
@@ -6345,6 +6519,7 @@ var codegens = [accessors, annotate, typeToSchema];
|
|
|
6345
6519
|
var outdatedEffectCodegen = createDiagnostic({
|
|
6346
6520
|
name: "outdatedEffectCodegen",
|
|
6347
6521
|
code: 19,
|
|
6522
|
+
description: "Detects when generated code is outdated and needs to be regenerated",
|
|
6348
6523
|
severity: "warning",
|
|
6349
6524
|
apply: fn("outdatedEffectCodegen.apply")(function* (sourceFile, _report) {
|
|
6350
6525
|
const codegensWithRanges = yield* getCodegensForSourceFile(codegens, sourceFile);
|
|
@@ -6390,11 +6565,12 @@ var outdatedEffectCodegen = createDiagnostic({
|
|
|
6390
6565
|
var overriddenSchemaConstructor = createDiagnostic({
|
|
6391
6566
|
name: "overriddenSchemaConstructor",
|
|
6392
6567
|
code: 30,
|
|
6568
|
+
description: "Prevents overriding constructors in Schema classes which breaks decoding behavior",
|
|
6393
6569
|
severity: "error",
|
|
6394
6570
|
apply: fn("overriddenSchemaConstructor.apply")(function* (sourceFile, report) {
|
|
6395
6571
|
const ts = yield* service(TypeScriptApi);
|
|
6396
6572
|
const typeParser = yield* service(TypeParser);
|
|
6397
|
-
const
|
|
6573
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
6398
6574
|
function isAllowedConstructor(node) {
|
|
6399
6575
|
if (node.body && node.body.statements.length === 1) {
|
|
6400
6576
|
const expressionStatement = node.body.statements[0];
|
|
@@ -6428,7 +6604,8 @@ var overriddenSchemaConstructor = createDiagnostic({
|
|
|
6428
6604
|
for (const heritageClause of node.heritageClauses) {
|
|
6429
6605
|
if (heritageClause.token === ts.SyntaxKind.ExtendsKeyword) {
|
|
6430
6606
|
for (const type of heritageClause.types) {
|
|
6431
|
-
const typeAtLocation =
|
|
6607
|
+
const typeAtLocation = typeCheckerUtils.getTypeAtLocation(type.expression);
|
|
6608
|
+
if (!typeAtLocation) continue;
|
|
6432
6609
|
const isSchema = yield* pipe(
|
|
6433
6610
|
typeParser.effectSchemaType(typeAtLocation, type.expression),
|
|
6434
6611
|
map4(() => true),
|
|
@@ -6525,10 +6702,11 @@ var overriddenSchemaConstructor = createDiagnostic({
|
|
|
6525
6702
|
var returnEffectInGen = createDiagnostic({
|
|
6526
6703
|
name: "returnEffectInGen",
|
|
6527
6704
|
code: 11,
|
|
6705
|
+
description: "Warns when returning an Effect in a generator causes nested Effect<Effect<...>>",
|
|
6528
6706
|
severity: "suggestion",
|
|
6529
6707
|
apply: fn("returnEffectInGen.apply")(function* (sourceFile, report) {
|
|
6530
6708
|
const ts = yield* service(TypeScriptApi);
|
|
6531
|
-
const
|
|
6709
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
6532
6710
|
const typeParser = yield* service(TypeParser);
|
|
6533
6711
|
const nodeToVisit = [];
|
|
6534
6712
|
const appendNodeToVisit = (node) => {
|
|
@@ -6546,7 +6724,8 @@ var returnEffectInGen = createDiagnostic({
|
|
|
6546
6724
|
(_) => ts.isFunctionExpression(_) || ts.isFunctionDeclaration(_) || ts.isMethodDeclaration(_) || ts.isArrowFunction(_) || ts.isGetAccessor(_)
|
|
6547
6725
|
);
|
|
6548
6726
|
if (!(generatorOrRegularFunction && "asteriskToken" in generatorOrRegularFunction && generatorOrRegularFunction.asteriskToken)) continue;
|
|
6549
|
-
const type =
|
|
6727
|
+
const type = typeCheckerUtils.getTypeAtLocation(node.expression);
|
|
6728
|
+
if (!type) continue;
|
|
6550
6729
|
const maybeEffect = yield* option(typeParser.strictEffectType(type, node.expression));
|
|
6551
6730
|
if (isSome2(maybeEffect)) {
|
|
6552
6731
|
if (generatorOrRegularFunction && generatorOrRegularFunction.parent) {
|
|
@@ -6592,6 +6771,7 @@ Nested Effect-able types may be intended if you plan to later manually flatten o
|
|
|
6592
6771
|
var runEffectInsideEffect = createDiagnostic({
|
|
6593
6772
|
name: "runEffectInsideEffect",
|
|
6594
6773
|
code: 32,
|
|
6774
|
+
description: "Suggests using Runtime methods instead of Effect.run* inside Effect contexts",
|
|
6595
6775
|
severity: "suggestion",
|
|
6596
6776
|
apply: fn("runEffectInsideEffect.apply")(function* (sourceFile, report) {
|
|
6597
6777
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -6731,6 +6911,7 @@ Consider extracting the Runtime by using for example Effect.runtime and then use
|
|
|
6731
6911
|
var schemaStructWithTag = createDiagnostic({
|
|
6732
6912
|
name: "schemaStructWithTag",
|
|
6733
6913
|
code: 34,
|
|
6914
|
+
description: "Suggests using Schema.TaggedStruct instead of Schema.Struct with _tag field",
|
|
6734
6915
|
severity: "suggestion",
|
|
6735
6916
|
apply: fn("schemaStructWithTag.apply")(function* (sourceFile, report) {
|
|
6736
6917
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -6810,6 +6991,7 @@ var schemaStructWithTag = createDiagnostic({
|
|
|
6810
6991
|
var schemaUnionOfLiterals = createDiagnostic({
|
|
6811
6992
|
name: "schemaUnionOfLiterals",
|
|
6812
6993
|
code: 33,
|
|
6994
|
+
description: "Simplifies Schema.Union of multiple Schema.Literal calls into single Schema.Literal",
|
|
6813
6995
|
severity: "off",
|
|
6814
6996
|
apply: fn("schemaUnionOfLiterals.apply")(function* (sourceFile, report) {
|
|
6815
6997
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -6883,6 +7065,7 @@ var schemaUnionOfLiterals = createDiagnostic({
|
|
|
6883
7065
|
var scopeInLayerEffect = createDiagnostic({
|
|
6884
7066
|
name: "scopeInLayerEffect",
|
|
6885
7067
|
code: 13,
|
|
7068
|
+
description: "Suggests using Layer.scoped instead of Layer.effect when Scope is in requirements",
|
|
6886
7069
|
severity: "warning",
|
|
6887
7070
|
apply: fn("scopeInLayerEffect.apply")(function* (sourceFile, report) {
|
|
6888
7071
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -6941,12 +7124,14 @@ Consider using "scoped" instead to get rid of the scope in the requirements.`,
|
|
|
6941
7124
|
const node = nodeToVisit.shift();
|
|
6942
7125
|
const layerEffectApiCall = parseLayerEffectApiCall(node);
|
|
6943
7126
|
if (layerEffectApiCall) {
|
|
6944
|
-
const type =
|
|
6945
|
-
|
|
6946
|
-
|
|
6947
|
-
|
|
6948
|
-
|
|
6949
|
-
|
|
7127
|
+
const type = typeCheckerUtils.getTypeAtLocation(node);
|
|
7128
|
+
if (type) {
|
|
7129
|
+
yield* pipe(
|
|
7130
|
+
typeParser.layerType(type, node),
|
|
7131
|
+
flatMap2(({ RIn }) => reportIfLayerRequireScope(RIn, node, layerEffectApiCall.methodIdentifier)),
|
|
7132
|
+
ignore
|
|
7133
|
+
);
|
|
7134
|
+
}
|
|
6950
7135
|
continue;
|
|
6951
7136
|
}
|
|
6952
7137
|
if (ts.isClassDeclaration(node) && node.name && node.heritageClauses) {
|
|
@@ -6974,6 +7159,7 @@ Consider using "scoped" instead to get rid of the scope in the requirements.`,
|
|
|
6974
7159
|
var strictBooleanExpressions = createDiagnostic({
|
|
6975
7160
|
name: "strictBooleanExpressions",
|
|
6976
7161
|
code: 17,
|
|
7162
|
+
description: "Enforces boolean types in conditional expressions for type safety",
|
|
6977
7163
|
severity: "off",
|
|
6978
7164
|
apply: fn("strictBooleanExpressions.apply")(function* (sourceFile, report) {
|
|
6979
7165
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -7015,7 +7201,8 @@ var strictBooleanExpressions = createDiagnostic({
|
|
|
7015
7201
|
if (!nodeToCheck) continue;
|
|
7016
7202
|
if (!conditionChecks.has(nodeToCheck.parent)) continue;
|
|
7017
7203
|
if (!ts.isExpression(nodeToCheck)) continue;
|
|
7018
|
-
const nodeType =
|
|
7204
|
+
const nodeType = typeCheckerUtils.getTypeAtLocation(nodeToCheck);
|
|
7205
|
+
if (!nodeType) continue;
|
|
7019
7206
|
const constrainedType = typeChecker.getBaseConstraintOfType(nodeType);
|
|
7020
7207
|
let typesToCheck = [constrainedType || nodeType];
|
|
7021
7208
|
while (typesToCheck.length > 0) {
|
|
@@ -7043,10 +7230,11 @@ var strictBooleanExpressions = createDiagnostic({
|
|
|
7043
7230
|
var strictEffectProvide = createDiagnostic({
|
|
7044
7231
|
name: "strictEffectProvide",
|
|
7045
7232
|
code: 27,
|
|
7233
|
+
description: "Warns when using Effect.provide with layers outside of application entry points",
|
|
7046
7234
|
severity: "off",
|
|
7047
7235
|
apply: fn("strictEffectProvide.apply")(function* (sourceFile, report) {
|
|
7048
7236
|
const ts = yield* service(TypeScriptApi);
|
|
7049
|
-
const
|
|
7237
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
7050
7238
|
const typeParser = yield* service(TypeParser);
|
|
7051
7239
|
const parseEffectProvideWithLayer = (node) => gen(function* () {
|
|
7052
7240
|
if (!ts.isCallExpression(node) || node.arguments.length === 0) {
|
|
@@ -7055,7 +7243,8 @@ var strictEffectProvide = createDiagnostic({
|
|
|
7055
7243
|
yield* typeParser.isNodeReferenceToEffectModuleApi("provide")(node.expression);
|
|
7056
7244
|
return yield* firstSuccessOf(
|
|
7057
7245
|
node.arguments.map((arg) => {
|
|
7058
|
-
const argType =
|
|
7246
|
+
const argType = typeCheckerUtils.getTypeAtLocation(arg);
|
|
7247
|
+
if (!argType) return typeParserIssue("Could not get argument type");
|
|
7059
7248
|
return typeParser.layerType(argType, arg);
|
|
7060
7249
|
})
|
|
7061
7250
|
);
|
|
@@ -7087,6 +7276,7 @@ var strictEffectProvide = createDiagnostic({
|
|
|
7087
7276
|
var tryCatchInEffectGen = createDiagnostic({
|
|
7088
7277
|
name: "tryCatchInEffectGen",
|
|
7089
7278
|
code: 15,
|
|
7279
|
+
description: "Discourages try/catch in Effect generators in favor of Effect error handling",
|
|
7090
7280
|
severity: "suggestion",
|
|
7091
7281
|
apply: fn("tryCatchInEffectGen.apply")(function* (sourceFile, report) {
|
|
7092
7282
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -7132,6 +7322,7 @@ var tryCatchInEffectGen = createDiagnostic({
|
|
|
7132
7322
|
var unknownInEffectCatch = createDiagnostic({
|
|
7133
7323
|
name: "unknownInEffectCatch",
|
|
7134
7324
|
code: 31,
|
|
7325
|
+
description: "Warns when catch callbacks return unknown instead of typed errors",
|
|
7135
7326
|
severity: "warning",
|
|
7136
7327
|
apply: fn("unknownInEffectCatch.apply")(function* (sourceFile, report) {
|
|
7137
7328
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -7189,6 +7380,7 @@ Consider wrapping unknown errors into Effect's Data.TaggedError for example, or
|
|
|
7189
7380
|
var unnecessaryEffectGen = createDiagnostic({
|
|
7190
7381
|
name: "unnecessaryEffectGen",
|
|
7191
7382
|
code: 5,
|
|
7383
|
+
description: "Suggests removing Effect.gen when it contains only a single return statement",
|
|
7192
7384
|
severity: "suggestion",
|
|
7193
7385
|
apply: fn("unnecessaryEffectGen.apply")(function* (sourceFile, report) {
|
|
7194
7386
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -7232,15 +7424,12 @@ var unnecessaryEffectGen = createDiagnostic({
|
|
|
7232
7424
|
var unnecessaryFailYieldableError = createDiagnostic({
|
|
7233
7425
|
name: "unnecessaryFailYieldableError",
|
|
7234
7426
|
code: 29,
|
|
7427
|
+
description: "Suggests yielding yieldable errors directly instead of wrapping with Effect.fail",
|
|
7235
7428
|
severity: "suggestion",
|
|
7236
7429
|
apply: fn("unnecessaryFailYieldableError.apply")(function* (sourceFile, report) {
|
|
7237
7430
|
const ts = yield* service(TypeScriptApi);
|
|
7238
7431
|
const typeParser = yield* service(TypeParser);
|
|
7239
|
-
const
|
|
7240
|
-
const yieldableErrorTypes = yield* pipe(
|
|
7241
|
-
typeParser.effectCauseYieldableErrorTypes(sourceFile),
|
|
7242
|
-
orElse2(() => succeed([]))
|
|
7243
|
-
);
|
|
7432
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
7244
7433
|
const nodeToVisit = [];
|
|
7245
7434
|
const appendNodeToVisit = (node) => {
|
|
7246
7435
|
nodeToVisit.push(node);
|
|
@@ -7254,32 +7443,34 @@ var unnecessaryFailYieldableError = createDiagnostic({
|
|
|
7254
7443
|
const callExpression = node.expression;
|
|
7255
7444
|
yield* pipe(
|
|
7256
7445
|
typeParser.isNodeReferenceToEffectModuleApi("fail")(callExpression.expression),
|
|
7257
|
-
|
|
7446
|
+
flatMap2(() => {
|
|
7258
7447
|
if (callExpression.arguments.length > 0) {
|
|
7259
7448
|
const failArgument = callExpression.arguments[0];
|
|
7260
|
-
const argumentType =
|
|
7261
|
-
|
|
7262
|
-
|
|
7449
|
+
const argumentType = typeCheckerUtils.getTypeAtLocation(failArgument);
|
|
7450
|
+
if (!argumentType) return void_;
|
|
7451
|
+
return pipe(
|
|
7452
|
+
typeParser.extendsCauseYieldableError(argumentType),
|
|
7453
|
+
map4(
|
|
7454
|
+
() => report({
|
|
7455
|
+
location: node,
|
|
7456
|
+
messageText: `This Effect.fail call uses a yieldable error type as argument. You can yield* the error directly instead.`,
|
|
7457
|
+
fixes: [{
|
|
7458
|
+
fixName: "unnecessaryFailYieldableError_fix",
|
|
7459
|
+
description: "Replace yield* Effect.fail with yield*",
|
|
7460
|
+
apply: gen(function* () {
|
|
7461
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
7462
|
+
changeTracker.replaceNode(
|
|
7463
|
+
sourceFile,
|
|
7464
|
+
callExpression,
|
|
7465
|
+
failArgument
|
|
7466
|
+
);
|
|
7467
|
+
})
|
|
7468
|
+
}]
|
|
7469
|
+
})
|
|
7470
|
+
)
|
|
7263
7471
|
);
|
|
7264
|
-
if (isYieldableError) {
|
|
7265
|
-
report({
|
|
7266
|
-
location: node,
|
|
7267
|
-
messageText: `This Effect.fail call uses a yieldable error type as argument. You can yield* the error directly instead.`,
|
|
7268
|
-
fixes: [{
|
|
7269
|
-
fixName: "unnecessaryFailYieldableError_fix",
|
|
7270
|
-
description: "Replace yield* Effect.fail with yield*",
|
|
7271
|
-
apply: gen(function* () {
|
|
7272
|
-
const changeTracker = yield* service(ChangeTracker);
|
|
7273
|
-
changeTracker.replaceNode(
|
|
7274
|
-
sourceFile,
|
|
7275
|
-
callExpression,
|
|
7276
|
-
failArgument
|
|
7277
|
-
);
|
|
7278
|
-
})
|
|
7279
|
-
}]
|
|
7280
|
-
});
|
|
7281
|
-
}
|
|
7282
7472
|
}
|
|
7473
|
+
return void_;
|
|
7283
7474
|
}),
|
|
7284
7475
|
ignore
|
|
7285
7476
|
);
|
|
@@ -7292,6 +7483,7 @@ var unnecessaryFailYieldableError = createDiagnostic({
|
|
|
7292
7483
|
var unnecessaryPipe = createDiagnostic({
|
|
7293
7484
|
name: "unnecessaryPipe",
|
|
7294
7485
|
code: 9,
|
|
7486
|
+
description: "Removes pipe calls with no arguments",
|
|
7295
7487
|
severity: "suggestion",
|
|
7296
7488
|
apply: fn("unnecessaryPipe.apply")(function* (sourceFile, report) {
|
|
7297
7489
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -7337,6 +7529,7 @@ var unnecessaryPipe = createDiagnostic({
|
|
|
7337
7529
|
var unnecessaryPipeChain = createDiagnostic({
|
|
7338
7530
|
name: "unnecessaryPipeChain",
|
|
7339
7531
|
code: 16,
|
|
7532
|
+
description: "Simplifies chained pipe calls into a single pipe call",
|
|
7340
7533
|
severity: "suggestion",
|
|
7341
7534
|
apply: fn("unnecessaryPipeChain.apply")(function* (sourceFile, report) {
|
|
7342
7535
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -7411,6 +7604,7 @@ var unnecessaryPipeChain = createDiagnostic({
|
|
|
7411
7604
|
var unsupportedServiceAccessors = createDiagnostic({
|
|
7412
7605
|
name: "unsupportedServiceAccessors",
|
|
7413
7606
|
code: 21,
|
|
7607
|
+
description: "Warns about service accessors that need codegen due to generic/complex signatures",
|
|
7414
7608
|
severity: "warning",
|
|
7415
7609
|
apply: fn("unsupportedServiceAccessors.apply")(function* (sourceFile, report) {
|
|
7416
7610
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -7498,7 +7692,8 @@ var diagnostics = [
|
|
|
7498
7692
|
unknownInEffectCatch,
|
|
7499
7693
|
runEffectInsideEffect,
|
|
7500
7694
|
schemaUnionOfLiterals,
|
|
7501
|
-
schemaStructWithTag
|
|
7695
|
+
schemaStructWithTag,
|
|
7696
|
+
globalErrorInEffectFailure
|
|
7502
7697
|
];
|
|
7503
7698
|
|
|
7504
7699
|
// src/transform.ts
|