@effect/language-service 0.55.1 → 0.55.3
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/cli.js +185 -15
- package/cli.js.map +1 -1
- package/effect-lsp-patch-utils.js +180 -6
- package/effect-lsp-patch-utils.js.map +1 -1
- package/index.js +267 -29
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +185 -15
- package/transform.js.map +1 -1
|
@@ -872,8 +872,9 @@ var contAll = Symbol.for("Nano.contAll");
|
|
|
872
872
|
var NanoYield = Symbol.for("Nano.yield");
|
|
873
873
|
var args = Symbol.for("Nano.args");
|
|
874
874
|
var NanoDefectException = class {
|
|
875
|
-
constructor(message) {
|
|
875
|
+
constructor(message, lastSpan) {
|
|
876
876
|
this.message = message;
|
|
877
|
+
this.lastSpan = lastSpan;
|
|
877
878
|
}
|
|
878
879
|
_tag = "@effect/language-service/NanoDefectException";
|
|
879
880
|
};
|
|
@@ -931,6 +932,7 @@ var NanoFiber = class {
|
|
|
931
932
|
_services = {};
|
|
932
933
|
_cache = {};
|
|
933
934
|
_perf = false;
|
|
935
|
+
_lastSpan = "";
|
|
934
936
|
runLoop(nano) {
|
|
935
937
|
let current = nano;
|
|
936
938
|
while (true) {
|
|
@@ -961,17 +963,21 @@ var WithSpanProto = {
|
|
|
961
963
|
[evaluate](fiber) {
|
|
962
964
|
const [fa, name] = this[args];
|
|
963
965
|
if (!fiber._perf) return fa;
|
|
966
|
+
const previousSpan = fiber._lastSpan;
|
|
967
|
+
fiber._lastSpan = name;
|
|
964
968
|
const start = performance.now();
|
|
965
969
|
timingsCount[name] = (timingsCount[name] || 0) + 1;
|
|
966
970
|
return match(fa, {
|
|
967
971
|
onSuccess: (_) => {
|
|
968
972
|
const end = performance.now();
|
|
969
973
|
timings[name] = (timings[name] || 0) + (end - start);
|
|
974
|
+
fiber._lastSpan = previousSpan;
|
|
970
975
|
return succeed(_);
|
|
971
976
|
},
|
|
972
977
|
onFailure: (_) => {
|
|
973
978
|
const end = performance.now();
|
|
974
979
|
timings[name] = (timings[name] || 0) + (end - start);
|
|
980
|
+
fiber._lastSpan = previousSpan;
|
|
975
981
|
return fail(_);
|
|
976
982
|
}
|
|
977
983
|
});
|
|
@@ -984,6 +990,7 @@ var withSpan = (name) => (fa) => {
|
|
|
984
990
|
};
|
|
985
991
|
var unsafeRun = (nano) => {
|
|
986
992
|
const fiber = new NanoFiber();
|
|
993
|
+
globalThis.currentFiber = fiber;
|
|
987
994
|
const result = fiber.runLoop(nano);
|
|
988
995
|
if (result._tag === "Success") {
|
|
989
996
|
return right2(result.value);
|
|
@@ -1094,7 +1101,7 @@ var ServiceProto = {
|
|
|
1094
1101
|
return cont2 ? cont2[contA](value, fiber) : fiber.yieldWith(succeed(value));
|
|
1095
1102
|
}
|
|
1096
1103
|
const cont = fiber.getCont(contE);
|
|
1097
|
-
return cont ? cont[contE](tag, fiber) : fiber.yieldWith(fail(new NanoDefectException(`Service ${tag.key} not found
|
|
1104
|
+
return cont ? cont[contE](tag, fiber) : fiber.yieldWith(fail(new NanoDefectException(`Service ${tag.key} not found`, fiber._lastSpan)));
|
|
1098
1105
|
}
|
|
1099
1106
|
};
|
|
1100
1107
|
var service = (tag) => {
|
|
@@ -1762,6 +1769,30 @@ function makeTypeScriptUtils(ts) {
|
|
|
1762
1769
|
}
|
|
1763
1770
|
return node;
|
|
1764
1771
|
}
|
|
1772
|
+
function isOuterExpression(node, kinds = ts.OuterExpressionKinds.All) {
|
|
1773
|
+
switch (node.kind) {
|
|
1774
|
+
case ts.SyntaxKind.ParenthesizedExpression:
|
|
1775
|
+
return (kinds & ts.OuterExpressionKinds.Parentheses) !== 0;
|
|
1776
|
+
case ts.SyntaxKind.TypeAssertionExpression:
|
|
1777
|
+
case ts.SyntaxKind.AsExpression:
|
|
1778
|
+
return (kinds & ts.OuterExpressionKinds.TypeAssertions) !== 0;
|
|
1779
|
+
case ts.SyntaxKind.SatisfiesExpression:
|
|
1780
|
+
return (kinds & (ts.OuterExpressionKinds.TypeAssertions | ts.OuterExpressionKinds.Satisfies)) !== 0;
|
|
1781
|
+
case ts.SyntaxKind.ExpressionWithTypeArguments:
|
|
1782
|
+
return (kinds & ts.OuterExpressionKinds.ExpressionsWithTypeArguments) !== 0;
|
|
1783
|
+
case ts.SyntaxKind.NonNullExpression:
|
|
1784
|
+
return (kinds & ts.OuterExpressionKinds.NonNullAssertions) !== 0;
|
|
1785
|
+
case ts.SyntaxKind.PartiallyEmittedExpression:
|
|
1786
|
+
return (kinds & ts.OuterExpressionKinds.PartiallyEmittedExpressions) !== 0;
|
|
1787
|
+
}
|
|
1788
|
+
return false;
|
|
1789
|
+
}
|
|
1790
|
+
function skipOuterExpressions(node, kinds = ts.OuterExpressionKinds.All) {
|
|
1791
|
+
while (isOuterExpression(node, kinds)) {
|
|
1792
|
+
node = node.expression;
|
|
1793
|
+
}
|
|
1794
|
+
return node;
|
|
1795
|
+
}
|
|
1765
1796
|
return {
|
|
1766
1797
|
findNodeAtPositionIncludingTrivia,
|
|
1767
1798
|
parsePackageContentNameAndVersionFromScope,
|
|
@@ -1782,7 +1813,9 @@ function makeTypeScriptUtils(ts) {
|
|
|
1782
1813
|
createEffectGenCallExpressionWithBlock,
|
|
1783
1814
|
createReturnYieldStarStatement,
|
|
1784
1815
|
parseAccessedExpressionForCompletion,
|
|
1785
|
-
getSourceFileOfNode
|
|
1816
|
+
getSourceFileOfNode,
|
|
1817
|
+
isOuterExpression,
|
|
1818
|
+
skipOuterExpressions
|
|
1786
1819
|
};
|
|
1787
1820
|
}
|
|
1788
1821
|
|
|
@@ -1867,6 +1900,14 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
|
|
|
1867
1900
|
result = node2;
|
|
1868
1901
|
return;
|
|
1869
1902
|
}
|
|
1903
|
+
if (ts.isPropertyAssignment(node2)) {
|
|
1904
|
+
const realStart = ts.getTokenPosOfNode(node2, sourceFile);
|
|
1905
|
+
const starts = sourceFile.getLineStarts().filter((start) => start >= node2.pos && start <= realStart);
|
|
1906
|
+
if (starts.length > 0) {
|
|
1907
|
+
result = node2;
|
|
1908
|
+
return;
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1870
1911
|
if (result) return;
|
|
1871
1912
|
if (node2.parent) find(node2.parent);
|
|
1872
1913
|
}
|
|
@@ -3566,6 +3607,103 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
3566
3607
|
};
|
|
3567
3608
|
}
|
|
3568
3609
|
|
|
3610
|
+
// src/diagnostics/anyUnknownInErrorContext.ts
|
|
3611
|
+
var anyUnknownInErrorContext = createDiagnostic({
|
|
3612
|
+
name: "anyUnknownInErrorContext",
|
|
3613
|
+
code: 28,
|
|
3614
|
+
severity: "off",
|
|
3615
|
+
apply: fn("anyUnknownInErrorContext.apply")(function* (sourceFile, report) {
|
|
3616
|
+
const ts = yield* service(TypeScriptApi);
|
|
3617
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
3618
|
+
const typeParser = yield* service(TypeParser);
|
|
3619
|
+
const isAnyOrUnknown = (type) => (type.flags & ts.TypeFlags.Any) > 0 || (type.flags & ts.TypeFlags.Unknown) > 0;
|
|
3620
|
+
const matchingNodes = [];
|
|
3621
|
+
const nodeToVisit = [sourceFile];
|
|
3622
|
+
const appendNodeToVisit = (node) => {
|
|
3623
|
+
nodeToVisit.push(node);
|
|
3624
|
+
return void 0;
|
|
3625
|
+
};
|
|
3626
|
+
while (nodeToVisit.length > 0) {
|
|
3627
|
+
const node = nodeToVisit.pop();
|
|
3628
|
+
if (ts.isTypeNode(node)) continue;
|
|
3629
|
+
if (ts.isTypeAliasDeclaration(node)) continue;
|
|
3630
|
+
if (ts.isInterfaceDeclaration(node)) continue;
|
|
3631
|
+
if (ts.isAsExpression(node) && node.type && node.type.kind === ts.SyntaxKind.AnyKeyword) {
|
|
3632
|
+
continue;
|
|
3633
|
+
}
|
|
3634
|
+
if (ts.isParameter(node) || ts.isPropertyDeclaration(node) || ts.isVariableDeclaration(node)) {
|
|
3635
|
+
if (node.type) {
|
|
3636
|
+
const type2 = typeChecker.getTypeAtLocation(node.type);
|
|
3637
|
+
const expectedEffect = yield* pipe(
|
|
3638
|
+
typeParser.strictEffectType(type2, node.type),
|
|
3639
|
+
orElse2(() => void_)
|
|
3640
|
+
);
|
|
3641
|
+
if (expectedEffect) continue;
|
|
3642
|
+
}
|
|
3643
|
+
}
|
|
3644
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
3645
|
+
if (!ts.isExpression(node)) continue;
|
|
3646
|
+
let type = typeChecker.getTypeAtLocation(node);
|
|
3647
|
+
if (ts.isCallExpression(node)) {
|
|
3648
|
+
const resolvedSignature = typeChecker.getResolvedSignature(node);
|
|
3649
|
+
if (resolvedSignature) {
|
|
3650
|
+
type = typeChecker.getReturnTypeOfSignature(resolvedSignature);
|
|
3651
|
+
}
|
|
3652
|
+
}
|
|
3653
|
+
if (!type) continue;
|
|
3654
|
+
yield* pipe(
|
|
3655
|
+
typeParser.strictEffectType(type, node),
|
|
3656
|
+
map4((effect) => {
|
|
3657
|
+
const { E, R } = effect;
|
|
3658
|
+
const hasAnyUnknownR = isAnyOrUnknown(R);
|
|
3659
|
+
const hasAnyUnknownE = isAnyOrUnknown(E);
|
|
3660
|
+
if (hasAnyUnknownR || hasAnyUnknownE) {
|
|
3661
|
+
const channels = [];
|
|
3662
|
+
if (hasAnyUnknownR) {
|
|
3663
|
+
const typeName = R.flags & ts.TypeFlags.Any ? "any" : "unknown";
|
|
3664
|
+
channels.push(`${typeName} in the requirements channel`);
|
|
3665
|
+
}
|
|
3666
|
+
if (hasAnyUnknownE) {
|
|
3667
|
+
const typeName = E.flags & ts.TypeFlags.Any ? "any" : "unknown";
|
|
3668
|
+
channels.push(`${typeName} in the error channel`);
|
|
3669
|
+
}
|
|
3670
|
+
const nodeStart = ts.getTokenPosOfNode(node, sourceFile);
|
|
3671
|
+
const nodeEnd = node.end;
|
|
3672
|
+
for (let i = matchingNodes.length - 1; i >= 0; i--) {
|
|
3673
|
+
const existing = matchingNodes[i];
|
|
3674
|
+
const existingStart = ts.getTokenPosOfNode(existing.node, sourceFile);
|
|
3675
|
+
const existingEnd = existing.node.end;
|
|
3676
|
+
if (existingStart <= nodeStart && existingEnd >= nodeEnd) {
|
|
3677
|
+
matchingNodes.splice(i, 1);
|
|
3678
|
+
}
|
|
3679
|
+
}
|
|
3680
|
+
const suggestions = [`This Effect has ${channels.join(" and ")} which is not recommended.`];
|
|
3681
|
+
if (hasAnyUnknownR) {
|
|
3682
|
+
suggestions.push(`Only service identifiers should appear in the requirements channel.`);
|
|
3683
|
+
}
|
|
3684
|
+
if (hasAnyUnknownE) {
|
|
3685
|
+
suggestions.push(
|
|
3686
|
+
`Having an unknown or any error type is not useful. Consider instead using specific error types baked by Data.TaggedError for example.`
|
|
3687
|
+
);
|
|
3688
|
+
}
|
|
3689
|
+
channels.push(`If you plan to later on manually cast the type, you can safely disable this diagnostic.`);
|
|
3690
|
+
const messageText = suggestions.join("\n");
|
|
3691
|
+
matchingNodes.push({ messageText, node, type });
|
|
3692
|
+
}
|
|
3693
|
+
}),
|
|
3694
|
+
ignore
|
|
3695
|
+
);
|
|
3696
|
+
}
|
|
3697
|
+
for (const { messageText, node } of matchingNodes) {
|
|
3698
|
+
report({
|
|
3699
|
+
location: node,
|
|
3700
|
+
messageText,
|
|
3701
|
+
fixes: []
|
|
3702
|
+
});
|
|
3703
|
+
}
|
|
3704
|
+
})
|
|
3705
|
+
});
|
|
3706
|
+
|
|
3569
3707
|
// src/diagnostics/catchUnfailableEffect.ts
|
|
3570
3708
|
var catchUnfailableEffect = createDiagnostic({
|
|
3571
3709
|
name: "catchUnfailableEffect",
|
|
@@ -4414,8 +4552,20 @@ var missedPipeableOpportunity = createDiagnostic({
|
|
|
4414
4552
|
while (nodeToVisit.length > 0) {
|
|
4415
4553
|
const node = nodeToVisit.shift();
|
|
4416
4554
|
if (ts.isCallExpression(node) && node.arguments.length === 1) {
|
|
4417
|
-
const
|
|
4418
|
-
|
|
4555
|
+
const isPipeCall = yield* pipe(typeParser.pipeCall(node), orElse2(() => void_));
|
|
4556
|
+
if (!isPipeCall) {
|
|
4557
|
+
const resolvedSignature = typeChecker.getResolvedSignature(node);
|
|
4558
|
+
if (resolvedSignature) {
|
|
4559
|
+
const returnType = typeChecker.getReturnTypeOfSignature(resolvedSignature);
|
|
4560
|
+
if (returnType) {
|
|
4561
|
+
const callSignatures = typeChecker.getSignaturesOfType(returnType, ts.SignatureKind.Call);
|
|
4562
|
+
if (callSignatures.length === 0) {
|
|
4563
|
+
const parentChain = callChainNodes.get(node) || [];
|
|
4564
|
+
callChainNodes.set(node.arguments[0], parentChain.concat(node));
|
|
4565
|
+
}
|
|
4566
|
+
}
|
|
4567
|
+
}
|
|
4568
|
+
}
|
|
4419
4569
|
} else if (callChainNodes.has(node) && ts.isExpression(node)) {
|
|
4420
4570
|
const parentChain = (callChainNodes.get(node) || []).slice();
|
|
4421
4571
|
const originalParentChain = parentChain.slice();
|
|
@@ -5412,6 +5562,26 @@ var overriddenSchemaConstructor = createDiagnostic({
|
|
|
5412
5562
|
const ts = yield* service(TypeScriptApi);
|
|
5413
5563
|
const typeParser = yield* service(TypeParser);
|
|
5414
5564
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
5565
|
+
function isAllowedConstructor(node) {
|
|
5566
|
+
if (node.body && node.body.statements.length === 1) {
|
|
5567
|
+
const expressionStatement = node.body.statements[0];
|
|
5568
|
+
if (ts.isExpressionStatement(expressionStatement)) {
|
|
5569
|
+
const maybeCallSuper = expressionStatement.expression;
|
|
5570
|
+
if (ts.isCallExpression(maybeCallSuper)) {
|
|
5571
|
+
if (maybeCallSuper.expression.kind === ts.SyntaxKind.SuperKeyword) {
|
|
5572
|
+
const expectedNames = node.parameters.map((_) => _.name).filter(ts.isIdentifier).map((_) => ts.idText(_));
|
|
5573
|
+
if (expectedNames.length === 2 && expectedNames.length === node.parameters.length) {
|
|
5574
|
+
const givenNames = maybeCallSuper.arguments.filter(ts.isIdentifier).map((_) => ts.idText(_));
|
|
5575
|
+
if (givenNames.length === expectedNames.length && givenNames.every((name, index) => name === expectedNames[index])) {
|
|
5576
|
+
return true;
|
|
5577
|
+
}
|
|
5578
|
+
}
|
|
5579
|
+
}
|
|
5580
|
+
}
|
|
5581
|
+
}
|
|
5582
|
+
}
|
|
5583
|
+
return false;
|
|
5584
|
+
}
|
|
5415
5585
|
const nodeToVisit = [];
|
|
5416
5586
|
const appendNodeToVisit = (node) => {
|
|
5417
5587
|
nodeToVisit.push(node);
|
|
@@ -5443,6 +5613,9 @@ var overriddenSchemaConstructor = createDiagnostic({
|
|
|
5443
5613
|
const members = node.members;
|
|
5444
5614
|
for (const member of members) {
|
|
5445
5615
|
if (ts.isConstructorDeclaration(member)) {
|
|
5616
|
+
if (isAllowedConstructor(member)) {
|
|
5617
|
+
continue;
|
|
5618
|
+
}
|
|
5446
5619
|
const fixAsStaticNew = {
|
|
5447
5620
|
fixName: "overriddenSchemaConstructor_static",
|
|
5448
5621
|
description: "Rewrite using the static 'new' pattern",
|
|
@@ -6240,6 +6413,7 @@ var unsupportedServiceAccessors = createDiagnostic({
|
|
|
6240
6413
|
|
|
6241
6414
|
// src/diagnostics.ts
|
|
6242
6415
|
var diagnostics = [
|
|
6416
|
+
anyUnknownInErrorContext,
|
|
6243
6417
|
catchUnfailableEffect,
|
|
6244
6418
|
classSelfMismatch,
|
|
6245
6419
|
duplicatePackage,
|
|
@@ -6330,7 +6504,7 @@ function checkSourceFileWorker(tsInstance, program, sourceFile, compilerOptions,
|
|
|
6330
6504
|
})
|
|
6331
6505
|
),
|
|
6332
6506
|
getOrElse((e) => {
|
|
6333
|
-
console.error(e);
|
|
6507
|
+
console.error(e.message, "at", e.lastSpan);
|
|
6334
6508
|
return [];
|
|
6335
6509
|
}),
|
|
6336
6510
|
map3(addDiagnostic)
|