@effect/language-service 0.25.1 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/cli.js +153 -4
- package/cli.js.map +1 -1
- package/index.js +215 -5
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +153 -4
- package/transform.js.map +1 -1
package/package.json
CHANGED
package/transform.js
CHANGED
|
@@ -2499,11 +2499,16 @@ function make2(ts, typeChecker) {
|
|
|
2499
2499
|
const pipeCall = cachedBy(
|
|
2500
2500
|
function(node) {
|
|
2501
2501
|
if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.isIdentifier(node.expression.name) && node.expression.name.text === "pipe") {
|
|
2502
|
-
return succeed({
|
|
2502
|
+
return succeed({
|
|
2503
|
+
node,
|
|
2504
|
+
subject: node.expression.expression,
|
|
2505
|
+
args: Array.from(node.arguments),
|
|
2506
|
+
kind: "pipeable"
|
|
2507
|
+
});
|
|
2503
2508
|
}
|
|
2504
2509
|
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === "pipe" && node.arguments.length > 0) {
|
|
2505
2510
|
const [subject, ...args2] = node.arguments;
|
|
2506
|
-
return succeed({ node, subject, args: args2 });
|
|
2511
|
+
return succeed({ node, subject, args: args2, kind: "pipe" });
|
|
2507
2512
|
}
|
|
2508
2513
|
return typeParserIssue("Node is not a pipe call", void 0, node);
|
|
2509
2514
|
},
|
|
@@ -2542,6 +2547,7 @@ function make2(ts, typeChecker) {
|
|
|
2542
2547
|
unnecessaryEffectGen: unnecessaryEffectGen2,
|
|
2543
2548
|
effectSchemaType,
|
|
2544
2549
|
contextTag,
|
|
2550
|
+
pipeableType,
|
|
2545
2551
|
pipeCall,
|
|
2546
2552
|
scopeType
|
|
2547
2553
|
};
|
|
@@ -3475,10 +3481,77 @@ Consider using "scoped" instead to get rid of the scope in the requirements.`,
|
|
|
3475
3481
|
})
|
|
3476
3482
|
});
|
|
3477
3483
|
|
|
3484
|
+
// src/diagnostics/strictBooleanExpressions.ts
|
|
3485
|
+
var strictBooleanExpressions = createDiagnostic({
|
|
3486
|
+
name: "strictBooleanExpressions",
|
|
3487
|
+
code: 17,
|
|
3488
|
+
severity: "off",
|
|
3489
|
+
apply: fn("strictBooleanExpressions.apply")(function* (sourceFile, report) {
|
|
3490
|
+
const ts = yield* service(TypeScriptApi);
|
|
3491
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
3492
|
+
const conditionChecks = /* @__PURE__ */ new WeakMap();
|
|
3493
|
+
const nodeToVisit = [];
|
|
3494
|
+
const appendNodeToVisit = (node) => {
|
|
3495
|
+
nodeToVisit.push(node);
|
|
3496
|
+
return void 0;
|
|
3497
|
+
};
|
|
3498
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
3499
|
+
while (nodeToVisit.length > 0) {
|
|
3500
|
+
const node = nodeToVisit.shift();
|
|
3501
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
3502
|
+
const nodes = [];
|
|
3503
|
+
if (ts.isIfStatement(node)) {
|
|
3504
|
+
conditionChecks.set(node, true);
|
|
3505
|
+
nodes.push(node.expression);
|
|
3506
|
+
} else if (ts.isWhileStatement(node)) {
|
|
3507
|
+
conditionChecks.set(node, true);
|
|
3508
|
+
nodes.push(node.expression);
|
|
3509
|
+
} else if (ts.isConditionalExpression(node)) {
|
|
3510
|
+
conditionChecks.set(node, true);
|
|
3511
|
+
nodes.push(node.condition);
|
|
3512
|
+
} else if (ts.isPrefixUnaryExpression(node) && node.operator === ts.SyntaxKind.ExclamationToken) {
|
|
3513
|
+
conditionChecks.set(node, true);
|
|
3514
|
+
nodes.push(node.operand);
|
|
3515
|
+
} else if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.BarBarToken) {
|
|
3516
|
+
if (conditionChecks.has(node.parent)) conditionChecks.set(node, true);
|
|
3517
|
+
nodes.push(node.left);
|
|
3518
|
+
nodes.push(node.right);
|
|
3519
|
+
} else if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {
|
|
3520
|
+
if (conditionChecks.has(node.parent)) conditionChecks.set(node, true);
|
|
3521
|
+
nodes.push(node.left);
|
|
3522
|
+
nodes.push(node.right);
|
|
3523
|
+
}
|
|
3524
|
+
for (const nodeToCheck of nodes) {
|
|
3525
|
+
if (!nodeToCheck) continue;
|
|
3526
|
+
if (!conditionChecks.has(nodeToCheck.parent)) continue;
|
|
3527
|
+
const nodeType = typeChecker.getTypeAtLocation(nodeToCheck);
|
|
3528
|
+
const constrainedType = typeChecker.getBaseConstraintOfType(nodeType);
|
|
3529
|
+
let typesToCheck = [constrainedType || nodeType];
|
|
3530
|
+
while (typesToCheck.length > 0) {
|
|
3531
|
+
const type = typesToCheck.pop();
|
|
3532
|
+
if (type.isUnion()) {
|
|
3533
|
+
typesToCheck = typesToCheck.concat(type.types);
|
|
3534
|
+
continue;
|
|
3535
|
+
}
|
|
3536
|
+
if (type.flags & ts.TypeFlags.Boolean) continue;
|
|
3537
|
+
if (type.flags & ts.TypeFlags.Never) continue;
|
|
3538
|
+
if (type.flags & ts.TypeFlags.BooleanLiteral) continue;
|
|
3539
|
+
const typeName = typeChecker.typeToString(type);
|
|
3540
|
+
report({
|
|
3541
|
+
node: nodeToCheck,
|
|
3542
|
+
messageText: `Unexpected \`${typeName}\` type in condition, expected strictly a boolean instead.`,
|
|
3543
|
+
fixes: []
|
|
3544
|
+
});
|
|
3545
|
+
}
|
|
3546
|
+
}
|
|
3547
|
+
}
|
|
3548
|
+
})
|
|
3549
|
+
});
|
|
3550
|
+
|
|
3478
3551
|
// src/diagnostics/tryCatchInEffectGen.ts
|
|
3479
3552
|
var tryCatchInEffectGen = createDiagnostic({
|
|
3480
3553
|
name: "tryCatchInEffectGen",
|
|
3481
|
-
code:
|
|
3554
|
+
code: 15,
|
|
3482
3555
|
severity: "suggestion",
|
|
3483
3556
|
apply: fn("tryCatchInEffectGen.apply")(function* (sourceFile, report) {
|
|
3484
3557
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -3608,6 +3681,80 @@ var unnecessaryPipe = createDiagnostic({
|
|
|
3608
3681
|
})
|
|
3609
3682
|
});
|
|
3610
3683
|
|
|
3684
|
+
// src/diagnostics/unnecessaryPipeChain.ts
|
|
3685
|
+
var unnecessaryPipeChain = createDiagnostic({
|
|
3686
|
+
name: "unnecessaryPipeChain",
|
|
3687
|
+
code: 16,
|
|
3688
|
+
severity: "suggestion",
|
|
3689
|
+
apply: fn("unnecessaryPipeChain.apply")(function* (sourceFile, report) {
|
|
3690
|
+
const ts = yield* service(TypeScriptApi);
|
|
3691
|
+
const typeParser = yield* service(TypeParser);
|
|
3692
|
+
const nodeToVisit = [];
|
|
3693
|
+
const appendNodeToVisit = (node) => {
|
|
3694
|
+
nodeToVisit.push(node);
|
|
3695
|
+
return void 0;
|
|
3696
|
+
};
|
|
3697
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
3698
|
+
while (nodeToVisit.length > 0) {
|
|
3699
|
+
const node = nodeToVisit.shift();
|
|
3700
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
3701
|
+
if (ts.isCallExpression(node)) {
|
|
3702
|
+
yield* pipe(
|
|
3703
|
+
typeParser.pipeCall(node),
|
|
3704
|
+
flatMap2(
|
|
3705
|
+
(pipeCall) => map3(typeParser.pipeCall(pipeCall.subject), (innerCall) => ({ pipeCall, innerCall }))
|
|
3706
|
+
),
|
|
3707
|
+
map3(({ innerCall, pipeCall }) => {
|
|
3708
|
+
report({
|
|
3709
|
+
node,
|
|
3710
|
+
messageText: `Chained pipe calls can be simplified to a single pipe call`,
|
|
3711
|
+
fixes: [{
|
|
3712
|
+
fixName: "unnecessaryPipeChain_fix",
|
|
3713
|
+
description: "Rewrite as single pipe call",
|
|
3714
|
+
apply: gen(function* () {
|
|
3715
|
+
const changeTracker = yield* service(
|
|
3716
|
+
ChangeTracker
|
|
3717
|
+
);
|
|
3718
|
+
switch (innerCall.kind) {
|
|
3719
|
+
case "pipe": {
|
|
3720
|
+
changeTracker.replaceNode(
|
|
3721
|
+
sourceFile,
|
|
3722
|
+
node,
|
|
3723
|
+
ts.factory.createCallExpression(
|
|
3724
|
+
ts.factory.createIdentifier("pipe"),
|
|
3725
|
+
void 0,
|
|
3726
|
+
[innerCall.subject, ...innerCall.args, ...pipeCall.args]
|
|
3727
|
+
)
|
|
3728
|
+
);
|
|
3729
|
+
break;
|
|
3730
|
+
}
|
|
3731
|
+
case "pipeable": {
|
|
3732
|
+
changeTracker.replaceNode(
|
|
3733
|
+
sourceFile,
|
|
3734
|
+
node,
|
|
3735
|
+
ts.factory.createCallExpression(
|
|
3736
|
+
ts.factory.createPropertyAccessExpression(
|
|
3737
|
+
innerCall.subject,
|
|
3738
|
+
"pipe"
|
|
3739
|
+
),
|
|
3740
|
+
void 0,
|
|
3741
|
+
[...innerCall.args, ...pipeCall.args]
|
|
3742
|
+
)
|
|
3743
|
+
);
|
|
3744
|
+
break;
|
|
3745
|
+
}
|
|
3746
|
+
}
|
|
3747
|
+
})
|
|
3748
|
+
}]
|
|
3749
|
+
});
|
|
3750
|
+
}),
|
|
3751
|
+
ignore
|
|
3752
|
+
);
|
|
3753
|
+
}
|
|
3754
|
+
}
|
|
3755
|
+
})
|
|
3756
|
+
});
|
|
3757
|
+
|
|
3611
3758
|
// src/diagnostics.ts
|
|
3612
3759
|
var diagnostics = [
|
|
3613
3760
|
duplicatePackage,
|
|
@@ -3624,7 +3771,9 @@ var diagnostics = [
|
|
|
3624
3771
|
tryCatchInEffectGen,
|
|
3625
3772
|
importFromBarrel,
|
|
3626
3773
|
scopeInLayerEffect,
|
|
3627
|
-
effectInVoidSuccess
|
|
3774
|
+
effectInVoidSuccess,
|
|
3775
|
+
unnecessaryPipeChain,
|
|
3776
|
+
strictBooleanExpressions
|
|
3628
3777
|
];
|
|
3629
3778
|
|
|
3630
3779
|
// src/transform.ts
|