@effect/language-service 0.28.1 → 0.28.2
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 +1 -0
- package/cli.js +106 -1
- package/cli.js.map +1 -1
- package/index.js +106 -1
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +106 -1
- package/transform.js.map +1 -1
package/index.js
CHANGED
|
@@ -3631,6 +3631,110 @@ var missingStarInYieldEffectGen = createDiagnostic({
|
|
|
3631
3631
|
})
|
|
3632
3632
|
});
|
|
3633
3633
|
|
|
3634
|
+
// src/diagnostics/multipleEffectProvide.ts
|
|
3635
|
+
var multipleEffectProvide = createDiagnostic({
|
|
3636
|
+
name: "multipleEffectProvide",
|
|
3637
|
+
code: 18,
|
|
3638
|
+
severity: "warning",
|
|
3639
|
+
apply: fn("multipleEffectProvide.apply")(function* (sourceFile, report) {
|
|
3640
|
+
const ts = yield* service(TypeScriptApi);
|
|
3641
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
3642
|
+
const typeParser = yield* service(TypeParser);
|
|
3643
|
+
const effectModuleIdentifier = yield* pipe(
|
|
3644
|
+
findImportedModuleIdentifierByPackageAndNameOrBarrel(
|
|
3645
|
+
sourceFile,
|
|
3646
|
+
"effect",
|
|
3647
|
+
"Effect"
|
|
3648
|
+
),
|
|
3649
|
+
map4((_) => _.text),
|
|
3650
|
+
orElse2(() => succeed("Effect"))
|
|
3651
|
+
);
|
|
3652
|
+
const layerModuleIdentifier = yield* pipe(
|
|
3653
|
+
findImportedModuleIdentifierByPackageAndNameOrBarrel(
|
|
3654
|
+
sourceFile,
|
|
3655
|
+
"effect",
|
|
3656
|
+
"Layer"
|
|
3657
|
+
),
|
|
3658
|
+
map4((_) => _.text),
|
|
3659
|
+
orElse2(() => succeed("Layer"))
|
|
3660
|
+
);
|
|
3661
|
+
const parseEffectProvideLayer = (node) => {
|
|
3662
|
+
if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.isIdentifier(node.expression.name) && node.expression.name.text === "provide" && node.arguments.length > 0) {
|
|
3663
|
+
const layer = node.arguments[0];
|
|
3664
|
+
const type = typeChecker.getTypeAtLocation(layer);
|
|
3665
|
+
return pipe(
|
|
3666
|
+
typeParser.importedEffectModule(node.expression.expression),
|
|
3667
|
+
flatMap2(() => typeParser.layerType(type, layer)),
|
|
3668
|
+
map4(() => ({ layer, node })),
|
|
3669
|
+
orElse2(() => void_)
|
|
3670
|
+
);
|
|
3671
|
+
}
|
|
3672
|
+
return void_;
|
|
3673
|
+
};
|
|
3674
|
+
const parsePipeCall = (node) => gen(function* () {
|
|
3675
|
+
const { args: args2 } = yield* typeParser.pipeCall(node);
|
|
3676
|
+
let currentChunk = 0;
|
|
3677
|
+
const previousLayers = [[]];
|
|
3678
|
+
for (const pipeArg of args2) {
|
|
3679
|
+
const parsedProvide = yield* parseEffectProvideLayer(pipeArg);
|
|
3680
|
+
if (parsedProvide) {
|
|
3681
|
+
previousLayers[currentChunk].push(parsedProvide);
|
|
3682
|
+
} else {
|
|
3683
|
+
currentChunk++;
|
|
3684
|
+
previousLayers.push([]);
|
|
3685
|
+
}
|
|
3686
|
+
}
|
|
3687
|
+
for (const chunk of previousLayers) {
|
|
3688
|
+
if (chunk.length < 2) continue;
|
|
3689
|
+
report({
|
|
3690
|
+
node: chunk[0].node,
|
|
3691
|
+
messageText: "Calling multiple subsequent times Effect.provide is an anti-pattern and can lead to service lifecycle issues. You should combine the layers and provide them once instead.",
|
|
3692
|
+
fixes: [{
|
|
3693
|
+
fixName: "multipleEffectProvide_fix",
|
|
3694
|
+
description: "Combine into a single provide",
|
|
3695
|
+
apply: gen(function* () {
|
|
3696
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
3697
|
+
changeTracker.deleteRange(sourceFile, {
|
|
3698
|
+
pos: chunk[0].node.getStart(sourceFile),
|
|
3699
|
+
end: chunk[chunk.length - 1].node.getEnd()
|
|
3700
|
+
});
|
|
3701
|
+
const newNode = ts.factory.createCallExpression(
|
|
3702
|
+
ts.factory.createPropertyAccessExpression(
|
|
3703
|
+
ts.factory.createIdentifier(effectModuleIdentifier),
|
|
3704
|
+
ts.factory.createIdentifier("provide")
|
|
3705
|
+
),
|
|
3706
|
+
void 0,
|
|
3707
|
+
[ts.factory.createCallExpression(
|
|
3708
|
+
ts.factory.createPropertyAccessExpression(
|
|
3709
|
+
ts.factory.createIdentifier(layerModuleIdentifier),
|
|
3710
|
+
ts.factory.createIdentifier("mergeAll")
|
|
3711
|
+
),
|
|
3712
|
+
void 0,
|
|
3713
|
+
chunk.map((c) => c.layer)
|
|
3714
|
+
)]
|
|
3715
|
+
);
|
|
3716
|
+
changeTracker.insertNodeAt(sourceFile, chunk[0].node.getStart(sourceFile), newNode);
|
|
3717
|
+
})
|
|
3718
|
+
}]
|
|
3719
|
+
});
|
|
3720
|
+
}
|
|
3721
|
+
});
|
|
3722
|
+
const nodeToVisit = [];
|
|
3723
|
+
const appendNodeToVisit = (node) => {
|
|
3724
|
+
nodeToVisit.push(node);
|
|
3725
|
+
return void 0;
|
|
3726
|
+
};
|
|
3727
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
3728
|
+
while (nodeToVisit.length > 0) {
|
|
3729
|
+
const node = nodeToVisit.shift();
|
|
3730
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
3731
|
+
if (ts.isCallExpression(node)) {
|
|
3732
|
+
yield* pipe(parsePipeCall(node), ignore);
|
|
3733
|
+
}
|
|
3734
|
+
}
|
|
3735
|
+
})
|
|
3736
|
+
});
|
|
3737
|
+
|
|
3634
3738
|
// src/diagnostics/returnEffectInGen.ts
|
|
3635
3739
|
var returnEffectInGen = createDiagnostic({
|
|
3636
3740
|
name: "returnEffectInGen",
|
|
@@ -4092,7 +4196,8 @@ var diagnostics = [
|
|
|
4092
4196
|
scopeInLayerEffect,
|
|
4093
4197
|
effectInVoidSuccess,
|
|
4094
4198
|
unnecessaryPipeChain,
|
|
4095
|
-
strictBooleanExpressions
|
|
4199
|
+
strictBooleanExpressions,
|
|
4200
|
+
multipleEffectProvide
|
|
4096
4201
|
];
|
|
4097
4202
|
|
|
4098
4203
|
// src/completions/effectDiagnosticsComment.ts
|