@effect/language-service 0.53.2 → 0.54.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 +1 -0
- package/cli.js +74 -4
- package/cli.js.map +1 -1
- package/effect-lsp-patch-utils.js +67 -10
- package/effect-lsp-patch-utils.js.map +1 -1
- package/index.js +59 -1
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +59 -1
- package/transform.js.map +1 -1
package/README.md
CHANGED
|
@@ -69,6 +69,7 @@ And you're done! You'll now be able to use a set of refactors and diagnostics th
|
|
|
69
69
|
- Warn when `@effect-diagnostics-next-line` comments have no effect (i.e., they don't suppress any diagnostic)
|
|
70
70
|
- Detect nested function calls that can be converted to pipeable style for better readability
|
|
71
71
|
- Warn when using catch functions (`catchAll`, `catch`, `catchIf`, `catchSome`, `catchTag`, `catchTags`) on effects that never fail
|
|
72
|
+
- Warn when catch callbacks in `Effect.tryPromise`, `Effect.tryMap`, or `Effect.tryMapPromise` return `unknown` or `any` types
|
|
72
73
|
|
|
73
74
|
### Completions
|
|
74
75
|
|
package/cli.js
CHANGED
|
@@ -35288,6 +35288,63 @@ var tryCatchInEffectGen = createDiagnostic({
|
|
|
35288
35288
|
})
|
|
35289
35289
|
});
|
|
35290
35290
|
|
|
35291
|
+
// src/diagnostics/unknownInEffectCatch.ts
|
|
35292
|
+
var unknownInEffectCatch = createDiagnostic({
|
|
35293
|
+
name: "unknownInEffectCatch",
|
|
35294
|
+
code: 31,
|
|
35295
|
+
severity: "warning",
|
|
35296
|
+
apply: fn2("unknownInEffectCatch.apply")(function* (sourceFile, report) {
|
|
35297
|
+
const ts = yield* service2(TypeScriptApi);
|
|
35298
|
+
const typeParser = yield* service2(TypeParser);
|
|
35299
|
+
const typeChecker = yield* service2(TypeCheckerApi);
|
|
35300
|
+
const nodeToVisit = [];
|
|
35301
|
+
const appendNodeToVisit = (node) => {
|
|
35302
|
+
nodeToVisit.push(node);
|
|
35303
|
+
return void 0;
|
|
35304
|
+
};
|
|
35305
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
35306
|
+
while (nodeToVisit.length > 0) {
|
|
35307
|
+
const node = nodeToVisit.shift();
|
|
35308
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
35309
|
+
if (ts.isCallExpression(node)) {
|
|
35310
|
+
const isEffectWithCatch = yield* pipe(
|
|
35311
|
+
typeParser.isNodeReferenceToEffectModuleApi("tryPromise")(node.expression),
|
|
35312
|
+
orElse14(() => typeParser.isNodeReferenceToEffectModuleApi("try")(node.expression)),
|
|
35313
|
+
orElse14(() => typeParser.isNodeReferenceToEffectModuleApi("tryMap")(node.expression)),
|
|
35314
|
+
orElse14(() => typeParser.isNodeReferenceToEffectModuleApi("tryMapPromise")(node.expression)),
|
|
35315
|
+
orElse14(() => void_8)
|
|
35316
|
+
);
|
|
35317
|
+
if (isEffectWithCatch) {
|
|
35318
|
+
const signature = typeChecker.getResolvedSignature(node);
|
|
35319
|
+
if (signature) {
|
|
35320
|
+
const objectType = typeChecker.getParameterType(signature, 0);
|
|
35321
|
+
const catchFunctionSymbol = typeChecker.getPropertyOfType(objectType, "catch");
|
|
35322
|
+
if (catchFunctionSymbol) {
|
|
35323
|
+
const catchFunctionType = typeChecker.getTypeOfSymbolAtLocation(catchFunctionSymbol, node);
|
|
35324
|
+
const signatures = typeChecker.getSignaturesOfType(catchFunctionType, ts.SignatureKind.Call);
|
|
35325
|
+
if (signatures.length > 0) {
|
|
35326
|
+
const returnType = typeChecker.getReturnTypeOfSignature(signatures[0]);
|
|
35327
|
+
if (returnType && (returnType.flags & ts.TypeFlags.Unknown || returnType.flags & ts.TypeFlags.Any)) {
|
|
35328
|
+
const nodeText = sourceFile.text.substring(
|
|
35329
|
+
ts.getTokenPosOfNode(node.expression, sourceFile),
|
|
35330
|
+
node.expression.end
|
|
35331
|
+
);
|
|
35332
|
+
report({
|
|
35333
|
+
location: node.expression,
|
|
35334
|
+
messageText: `The 'catch' callback in ${nodeText} returns 'unknown'. The catch callback should be used to provide typed errors.
|
|
35335
|
+
Consider wrapping unknown errors into Effect's Data.TaggedError for example, or narrow down the type to the specific error raised.`,
|
|
35336
|
+
fixes: []
|
|
35337
|
+
});
|
|
35338
|
+
}
|
|
35339
|
+
}
|
|
35340
|
+
}
|
|
35341
|
+
}
|
|
35342
|
+
}
|
|
35343
|
+
}
|
|
35344
|
+
}
|
|
35345
|
+
})
|
|
35346
|
+
});
|
|
35347
|
+
|
|
35291
35348
|
// src/diagnostics/unnecessaryEffectGen.ts
|
|
35292
35349
|
var unnecessaryEffectGen = createDiagnostic({
|
|
35293
35350
|
name: "unnecessaryEffectGen",
|
|
@@ -35535,7 +35592,8 @@ var diagnostics = [
|
|
|
35535
35592
|
nonObjectEffectServiceType,
|
|
35536
35593
|
deterministicKeys,
|
|
35537
35594
|
missedPipeableOpportunity,
|
|
35538
|
-
strictEffectProvide
|
|
35595
|
+
strictEffectProvide,
|
|
35596
|
+
unknownInEffectCatch
|
|
35539
35597
|
];
|
|
35540
35598
|
|
|
35541
35599
|
// src/cli/diagnostics.ts
|
|
@@ -35596,6 +35654,13 @@ var diagnostics2 = make58(
|
|
|
35596
35654
|
}
|
|
35597
35655
|
const filesToCheckArray = fromIterable(filesToCheck);
|
|
35598
35656
|
const batches = chunksOf(filesToCheckArray, BATCH_SIZE);
|
|
35657
|
+
let lastLanguageService;
|
|
35658
|
+
const disposeIfLanguageServiceChanged = (languageService) => {
|
|
35659
|
+
if (lastLanguageService !== languageService) {
|
|
35660
|
+
lastLanguageService?.dispose();
|
|
35661
|
+
lastLanguageService = languageService;
|
|
35662
|
+
}
|
|
35663
|
+
};
|
|
35599
35664
|
for (const batch of batches) {
|
|
35600
35665
|
const { service: service3 } = (0, import_project_service.createProjectService)({ options: { loadTypeScriptPlugins: false } });
|
|
35601
35666
|
for (const filePath of batch) {
|
|
@@ -35605,6 +35670,7 @@ var diagnostics2 = make58(
|
|
|
35605
35670
|
if (!scriptInfo) continue;
|
|
35606
35671
|
const project4 = scriptInfo.getDefaultProject();
|
|
35607
35672
|
const languageService = project4.getLanguageService(true);
|
|
35673
|
+
disposeIfLanguageServiceChanged(languageService);
|
|
35608
35674
|
const program = languageService.getProgram();
|
|
35609
35675
|
if (!program) continue;
|
|
35610
35676
|
const sourceFile = program.getSourceFile(filePath);
|
|
@@ -35621,7 +35687,7 @@ var diagnostics2 = make58(
|
|
|
35621
35687
|
provideService7(TypeScriptApi, tsInstance),
|
|
35622
35688
|
provideService7(
|
|
35623
35689
|
LanguageServicePluginOptions,
|
|
35624
|
-
parse4(pluginConfig)
|
|
35690
|
+
{ ...parse4(pluginConfig), diagnosticsName: false }
|
|
35625
35691
|
),
|
|
35626
35692
|
run9,
|
|
35627
35693
|
map((_) => _.diagnostics),
|
|
@@ -35637,11 +35703,14 @@ var diagnostics2 = make58(
|
|
|
35637
35703
|
warningsCount += results.filter((_) => _.category === tsInstance.DiagnosticCategory.Warning).length;
|
|
35638
35704
|
messagesCount += results.filter((_) => _.category === tsInstance.DiagnosticCategory.Message).length;
|
|
35639
35705
|
if (results.length > 0) {
|
|
35640
|
-
|
|
35706
|
+
let formattedResults = tsInstance.formatDiagnosticsWithColorAndContext(results, {
|
|
35641
35707
|
getCanonicalFileName: (fileName) => path2.resolve(fileName),
|
|
35642
35708
|
getCurrentDirectory: () => path2.resolve("."),
|
|
35643
35709
|
getNewLine: () => "\n"
|
|
35644
35710
|
});
|
|
35711
|
+
Object.values(diagnostics).forEach(
|
|
35712
|
+
(_) => formattedResults = formattedResults.replace(new RegExp(`TS${_.code}:`, "g"), `effect(${_.name}):`)
|
|
35713
|
+
);
|
|
35645
35714
|
console.log(formattedResults);
|
|
35646
35715
|
}
|
|
35647
35716
|
} finally {
|
|
@@ -35650,6 +35719,7 @@ var diagnostics2 = make58(
|
|
|
35650
35719
|
}
|
|
35651
35720
|
yield* yieldNow4();
|
|
35652
35721
|
}
|
|
35722
|
+
disposeIfLanguageServiceChanged(void 0);
|
|
35653
35723
|
console.log(
|
|
35654
35724
|
`Checked ${checkedFilesCount} files out of ${filesToCheck.size} files.
|
|
35655
35725
|
${errorsCount} errors, ${warningsCount} warnings and ${messagesCount} messages.`
|
|
@@ -35782,7 +35852,7 @@ var getPatchesForModule = fn("getPatchesForModule")(
|
|
|
35782
35852
|
sourceFile.text,
|
|
35783
35853
|
insertCheckSourceFilePosition.value.position,
|
|
35784
35854
|
insertCheckSourceFilePosition.value.position,
|
|
35785
|
-
`effectLspPatchUtils().checkSourceFileWorker(${moduleName === "typescript" ? "module.exports" : "effectLspTypeScriptApis()"}, host, node, compilerOptions, diagnostics.add)
|
|
35855
|
+
`effectLspPatchUtils().checkSourceFileWorker(${moduleName === "typescript" ? "module.exports" : "effectLspTypeScriptApis()"}, host, node, compilerOptions, diagnostics.add, "${moduleName}")
|
|
35786
35856
|
`,
|
|
35787
35857
|
"\n",
|
|
35788
35858
|
version
|