@effect/language-service 0.55.5 → 0.57.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 +9 -0
- package/cli.js +709 -361
- package/cli.js.map +1 -1
- package/effect-lsp-patch-utils.js +197 -1
- package/effect-lsp-patch-utils.js.map +1 -1
- package/index.js +193 -1
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +197 -1
- package/transform.js.map +1 -1
package/index.js
CHANGED
|
@@ -2799,6 +2799,51 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
2799
2799
|
if (!symbol3) return typeParserIssue("Node has no symbol", void 0, givenNode);
|
|
2800
2800
|
return isSymbolExportOfPackageModule(symbol3, packageName, memberName, isCorrectSourceFile);
|
|
2801
2801
|
};
|
|
2802
|
+
const findSymbolsMatchingPackageAndExportedName = (packageName, exportedSymbolName) => cachedBy(
|
|
2803
|
+
fn("TypeParser.findSymbolsMatchingPackageAndExportedName")(function* (_fromSourceFile) {
|
|
2804
|
+
const result = [];
|
|
2805
|
+
for (const sourceFile of program.getSourceFiles()) {
|
|
2806
|
+
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
|
2807
|
+
if (!moduleSymbol) continue;
|
|
2808
|
+
const symbol3 = typeChecker.tryGetMemberInModuleExports(exportedSymbolName, moduleSymbol);
|
|
2809
|
+
if (!symbol3) continue;
|
|
2810
|
+
const packageInfo = yield* getSourceFilePackageInfo(sourceFile);
|
|
2811
|
+
if (!packageInfo || packageInfo.name.toLowerCase() !== packageName.toLowerCase()) continue;
|
|
2812
|
+
result.push([symbol3, sourceFile]);
|
|
2813
|
+
}
|
|
2814
|
+
return result;
|
|
2815
|
+
}),
|
|
2816
|
+
`TypeParser.findSymbolsMatchingPackageAndExportedName(${packageName}, ${exportedSymbolName})`,
|
|
2817
|
+
(sourceFile) => sourceFile
|
|
2818
|
+
);
|
|
2819
|
+
const isCauseTypeSourceFile = cachedBy(
|
|
2820
|
+
fn("TypeParser.isCauseTypeSourceFile")(function* (sourceFile) {
|
|
2821
|
+
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
|
2822
|
+
if (!moduleSymbol) return yield* typeParserIssue("Node has no symbol", void 0, sourceFile);
|
|
2823
|
+
const causeTypeSymbol = typeChecker.tryGetMemberInModuleExports("Cause", moduleSymbol);
|
|
2824
|
+
if (!causeTypeSymbol) return yield* typeParserIssue("Cause type not found", void 0, sourceFile);
|
|
2825
|
+
const type = typeChecker.getDeclaredTypeOfSymbol(causeTypeSymbol);
|
|
2826
|
+
yield* pipeableType(type, sourceFile);
|
|
2827
|
+
return sourceFile;
|
|
2828
|
+
}),
|
|
2829
|
+
"TypeParser.isCauseTypeSourceFile",
|
|
2830
|
+
(sourceFile) => sourceFile
|
|
2831
|
+
);
|
|
2832
|
+
const effectCauseYieldableErrorTypes = cachedBy(
|
|
2833
|
+
fn("TypeParser.effectCauseYieldableErrorTypes")(function* (fromSourceFile) {
|
|
2834
|
+
const symbols = yield* findSymbolsMatchingPackageAndExportedName("effect", "YieldableError")(fromSourceFile);
|
|
2835
|
+
const result = [];
|
|
2836
|
+
for (const [symbol3, sourceFile] of symbols) {
|
|
2837
|
+
const causeFile = yield* isCauseTypeSourceFile(sourceFile);
|
|
2838
|
+
if (!causeFile) continue;
|
|
2839
|
+
const type = typeChecker.getDeclaredTypeOfSymbol(symbol3);
|
|
2840
|
+
result.push(type);
|
|
2841
|
+
}
|
|
2842
|
+
return result;
|
|
2843
|
+
}),
|
|
2844
|
+
"TypeParser.effectCauseYieldableErrorTypes",
|
|
2845
|
+
(fromSourceFile) => fromSourceFile
|
|
2846
|
+
);
|
|
2802
2847
|
function covariantTypeArgument(type) {
|
|
2803
2848
|
const signatures = typeChecker.getSignaturesOfType(type, ts.SignatureKind.Call);
|
|
2804
2849
|
if (signatures.length !== 1) {
|
|
@@ -3788,6 +3833,7 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
3788
3833
|
effectGen,
|
|
3789
3834
|
effectFnUntracedGen,
|
|
3790
3835
|
effectFnGen,
|
|
3836
|
+
effectCauseYieldableErrorTypes,
|
|
3791
3837
|
unnecessaryEffectGen: unnecessaryEffectGen2,
|
|
3792
3838
|
effectSchemaType,
|
|
3793
3839
|
contextTag,
|
|
@@ -4098,8 +4144,93 @@ var accessors = createCodegen({
|
|
|
4098
4144
|
})
|
|
4099
4145
|
});
|
|
4100
4146
|
|
|
4147
|
+
// src/codegens/annotate.ts
|
|
4148
|
+
var annotate = createCodegen({
|
|
4149
|
+
name: "annotate",
|
|
4150
|
+
apply: fn("annotate.apply")(function* (sourceFile, textRange) {
|
|
4151
|
+
const ts = yield* service(TypeScriptApi);
|
|
4152
|
+
const tsUtils = yield* service(TypeScriptUtils);
|
|
4153
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
4154
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
4155
|
+
const parse3 = (node) => gen(function* () {
|
|
4156
|
+
let variableDeclarations = [];
|
|
4157
|
+
const result = [];
|
|
4158
|
+
if (ts.isVariableStatement(node)) {
|
|
4159
|
+
variableDeclarations = [...variableDeclarations, ...node.declarationList.declarations];
|
|
4160
|
+
} else if (ts.isVariableDeclarationList(node)) {
|
|
4161
|
+
variableDeclarations = [...variableDeclarations, ...node.declarations];
|
|
4162
|
+
} else if (ts.isVariableDeclaration(node)) {
|
|
4163
|
+
variableDeclarations = [...variableDeclarations, node];
|
|
4164
|
+
}
|
|
4165
|
+
if (variableDeclarations.length === 0) {
|
|
4166
|
+
return yield* fail(new CodegenNotApplicableError("not a variable declaration"));
|
|
4167
|
+
}
|
|
4168
|
+
for (const variableDeclaration of variableDeclarations) {
|
|
4169
|
+
if (!variableDeclaration.initializer) continue;
|
|
4170
|
+
const initializerType = typeChecker.getTypeAtLocation(variableDeclaration.initializer);
|
|
4171
|
+
const initializerTypeNode = fromNullable(typeCheckerUtils.typeToSimplifiedTypeNode(
|
|
4172
|
+
initializerType,
|
|
4173
|
+
node,
|
|
4174
|
+
ts.NodeBuilderFlags.NoTruncation
|
|
4175
|
+
)).pipe(
|
|
4176
|
+
orElse(
|
|
4177
|
+
() => fromNullable(typeCheckerUtils.typeToSimplifiedTypeNode(
|
|
4178
|
+
initializerType,
|
|
4179
|
+
void 0,
|
|
4180
|
+
ts.NodeBuilderFlags.NoTruncation
|
|
4181
|
+
))
|
|
4182
|
+
),
|
|
4183
|
+
getOrUndefined
|
|
4184
|
+
);
|
|
4185
|
+
if (!initializerTypeNode) continue;
|
|
4186
|
+
const typeNodeString = typeChecker.typeToString(initializerType, void 0, ts.TypeFormatFlags.NoTruncation);
|
|
4187
|
+
const hash3 = cyrb53(typeNodeString);
|
|
4188
|
+
result.push({ variableDeclaration, initializerTypeNode, hash: hash3 });
|
|
4189
|
+
}
|
|
4190
|
+
if (result.length === 0) {
|
|
4191
|
+
return yield* fail(new CodegenNotApplicableError("no variable declarations with initializers"));
|
|
4192
|
+
}
|
|
4193
|
+
const hash2 = cyrb53(result.map((_) => _.hash).join("/"));
|
|
4194
|
+
return {
|
|
4195
|
+
hash: hash2,
|
|
4196
|
+
result
|
|
4197
|
+
};
|
|
4198
|
+
});
|
|
4199
|
+
const nodeAndCommentRange = tsUtils.findNodeWithLeadingCommentAtPosition(sourceFile, textRange.pos);
|
|
4200
|
+
if (!nodeAndCommentRange) return yield* fail(new CodegenNotApplicableError("no node and comment range"));
|
|
4201
|
+
return yield* pipe(
|
|
4202
|
+
parse3(nodeAndCommentRange.node),
|
|
4203
|
+
map5(
|
|
4204
|
+
(_) => ({
|
|
4205
|
+
hash: _.hash,
|
|
4206
|
+
description: "Annotate with type",
|
|
4207
|
+
apply: gen(function* () {
|
|
4208
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
4209
|
+
for (const { initializerTypeNode, variableDeclaration } of _.result) {
|
|
4210
|
+
if (variableDeclaration.type) {
|
|
4211
|
+
changeTracker.deleteRange(sourceFile, {
|
|
4212
|
+
pos: variableDeclaration.name.end,
|
|
4213
|
+
end: variableDeclaration.type.end
|
|
4214
|
+
});
|
|
4215
|
+
}
|
|
4216
|
+
changeTracker.insertNodeAt(
|
|
4217
|
+
sourceFile,
|
|
4218
|
+
variableDeclaration.name.end,
|
|
4219
|
+
initializerTypeNode,
|
|
4220
|
+
{
|
|
4221
|
+
prefix: ": "
|
|
4222
|
+
}
|
|
4223
|
+
);
|
|
4224
|
+
}
|
|
4225
|
+
})
|
|
4226
|
+
})
|
|
4227
|
+
)
|
|
4228
|
+
);
|
|
4229
|
+
})
|
|
4230
|
+
});
|
|
4231
|
+
|
|
4101
4232
|
// src/codegens.ts
|
|
4102
|
-
var codegens = [accessors];
|
|
4233
|
+
var codegens = [accessors, annotate];
|
|
4103
4234
|
|
|
4104
4235
|
// src/completions/effectCodegensComment.ts
|
|
4105
4236
|
var effectCodegensComment = createCompletion({
|
|
@@ -8711,6 +8842,66 @@ var unnecessaryEffectGen = createDiagnostic({
|
|
|
8711
8842
|
})
|
|
8712
8843
|
});
|
|
8713
8844
|
|
|
8845
|
+
// src/diagnostics/unnecessaryFailYieldableError.ts
|
|
8846
|
+
var unnecessaryFailYieldableError = createDiagnostic({
|
|
8847
|
+
name: "unnecessaryFailYieldableError",
|
|
8848
|
+
code: 29,
|
|
8849
|
+
severity: "suggestion",
|
|
8850
|
+
apply: fn("unnecessaryFailYieldableError.apply")(function* (sourceFile, report) {
|
|
8851
|
+
const ts = yield* service(TypeScriptApi);
|
|
8852
|
+
const typeParser = yield* service(TypeParser);
|
|
8853
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
8854
|
+
const yieldableErrorTypes = yield* pipe(
|
|
8855
|
+
typeParser.effectCauseYieldableErrorTypes(sourceFile),
|
|
8856
|
+
orElse2(() => succeed([]))
|
|
8857
|
+
);
|
|
8858
|
+
const nodeToVisit = [];
|
|
8859
|
+
const appendNodeToVisit = (node) => {
|
|
8860
|
+
nodeToVisit.push(node);
|
|
8861
|
+
return void 0;
|
|
8862
|
+
};
|
|
8863
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
8864
|
+
while (nodeToVisit.length > 0) {
|
|
8865
|
+
const node = nodeToVisit.shift();
|
|
8866
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
8867
|
+
if (ts.isYieldExpression(node) && node.asteriskToken && node.expression && ts.isCallExpression(node.expression)) {
|
|
8868
|
+
const callExpression = node.expression;
|
|
8869
|
+
yield* pipe(
|
|
8870
|
+
typeParser.isNodeReferenceToEffectModuleApi("fail")(callExpression.expression),
|
|
8871
|
+
map5(() => {
|
|
8872
|
+
if (callExpression.arguments.length > 0) {
|
|
8873
|
+
const failArgument = callExpression.arguments[0];
|
|
8874
|
+
const argumentType = typeChecker.getTypeAtLocation(failArgument);
|
|
8875
|
+
const isYieldableError = yieldableErrorTypes.some(
|
|
8876
|
+
(yieldableType) => typeChecker.isTypeAssignableTo(argumentType, yieldableType)
|
|
8877
|
+
);
|
|
8878
|
+
if (isYieldableError) {
|
|
8879
|
+
report({
|
|
8880
|
+
location: node,
|
|
8881
|
+
messageText: `This Effect.fail call uses a yieldable error type as argument. You can yield* the error directly instead.`,
|
|
8882
|
+
fixes: [{
|
|
8883
|
+
fixName: "unnecessaryFailYieldableError_fix",
|
|
8884
|
+
description: "Replace yield* Effect.fail with yield*",
|
|
8885
|
+
apply: gen(function* () {
|
|
8886
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
8887
|
+
changeTracker.replaceNode(
|
|
8888
|
+
sourceFile,
|
|
8889
|
+
callExpression,
|
|
8890
|
+
failArgument
|
|
8891
|
+
);
|
|
8892
|
+
})
|
|
8893
|
+
}]
|
|
8894
|
+
});
|
|
8895
|
+
}
|
|
8896
|
+
}
|
|
8897
|
+
}),
|
|
8898
|
+
ignore
|
|
8899
|
+
);
|
|
8900
|
+
}
|
|
8901
|
+
}
|
|
8902
|
+
})
|
|
8903
|
+
});
|
|
8904
|
+
|
|
8714
8905
|
// src/diagnostics/unnecessaryPipe.ts
|
|
8715
8906
|
var unnecessaryPipe = createDiagnostic({
|
|
8716
8907
|
name: "unnecessaryPipe",
|
|
@@ -8898,6 +9089,7 @@ var diagnostics = [
|
|
|
8898
9089
|
floatingEffect,
|
|
8899
9090
|
missingStarInYieldEffectGen,
|
|
8900
9091
|
unnecessaryEffectGen,
|
|
9092
|
+
unnecessaryFailYieldableError,
|
|
8901
9093
|
missingReturnYieldStar,
|
|
8902
9094
|
leakingRequirements,
|
|
8903
9095
|
unnecessaryPipe,
|