@effect/language-service 0.53.3 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect/language-service",
3
- "version": "0.53.3",
3
+ "version": "0.54.0",
4
4
  "description": "A Language-Service Plugin to Refactor and Diagnostic effect-ts projects",
5
5
  "main": "index.cjs",
6
6
  "bin": {
package/transform.js CHANGED
@@ -5830,6 +5830,63 @@ var tryCatchInEffectGen = createDiagnostic({
5830
5830
  })
5831
5831
  });
5832
5832
 
5833
+ // src/diagnostics/unknownInEffectCatch.ts
5834
+ var unknownInEffectCatch = createDiagnostic({
5835
+ name: "unknownInEffectCatch",
5836
+ code: 31,
5837
+ severity: "warning",
5838
+ apply: fn("unknownInEffectCatch.apply")(function* (sourceFile, report) {
5839
+ const ts = yield* service(TypeScriptApi);
5840
+ const typeParser = yield* service(TypeParser);
5841
+ const typeChecker = yield* service(TypeCheckerApi);
5842
+ const nodeToVisit = [];
5843
+ const appendNodeToVisit = (node) => {
5844
+ nodeToVisit.push(node);
5845
+ return void 0;
5846
+ };
5847
+ ts.forEachChild(sourceFile, appendNodeToVisit);
5848
+ while (nodeToVisit.length > 0) {
5849
+ const node = nodeToVisit.shift();
5850
+ ts.forEachChild(node, appendNodeToVisit);
5851
+ if (ts.isCallExpression(node)) {
5852
+ const isEffectWithCatch = yield* pipe(
5853
+ typeParser.isNodeReferenceToEffectModuleApi("tryPromise")(node.expression),
5854
+ orElse2(() => typeParser.isNodeReferenceToEffectModuleApi("try")(node.expression)),
5855
+ orElse2(() => typeParser.isNodeReferenceToEffectModuleApi("tryMap")(node.expression)),
5856
+ orElse2(() => typeParser.isNodeReferenceToEffectModuleApi("tryMapPromise")(node.expression)),
5857
+ orElse2(() => void_)
5858
+ );
5859
+ if (isEffectWithCatch) {
5860
+ const signature = typeChecker.getResolvedSignature(node);
5861
+ if (signature) {
5862
+ const objectType = typeChecker.getParameterType(signature, 0);
5863
+ const catchFunctionSymbol = typeChecker.getPropertyOfType(objectType, "catch");
5864
+ if (catchFunctionSymbol) {
5865
+ const catchFunctionType = typeChecker.getTypeOfSymbolAtLocation(catchFunctionSymbol, node);
5866
+ const signatures = typeChecker.getSignaturesOfType(catchFunctionType, ts.SignatureKind.Call);
5867
+ if (signatures.length > 0) {
5868
+ const returnType = typeChecker.getReturnTypeOfSignature(signatures[0]);
5869
+ if (returnType && (returnType.flags & ts.TypeFlags.Unknown || returnType.flags & ts.TypeFlags.Any)) {
5870
+ const nodeText = sourceFile.text.substring(
5871
+ ts.getTokenPosOfNode(node.expression, sourceFile),
5872
+ node.expression.end
5873
+ );
5874
+ report({
5875
+ location: node.expression,
5876
+ messageText: `The 'catch' callback in ${nodeText} returns 'unknown'. The catch callback should be used to provide typed errors.
5877
+ Consider wrapping unknown errors into Effect's Data.TaggedError for example, or narrow down the type to the specific error raised.`,
5878
+ fixes: []
5879
+ });
5880
+ }
5881
+ }
5882
+ }
5883
+ }
5884
+ }
5885
+ }
5886
+ }
5887
+ })
5888
+ });
5889
+
5833
5890
  // src/diagnostics/unnecessaryEffectGen.ts
5834
5891
  var unnecessaryEffectGen = createDiagnostic({
5835
5892
  name: "unnecessaryEffectGen",
@@ -6077,7 +6134,8 @@ var diagnostics = [
6077
6134
  nonObjectEffectServiceType,
6078
6135
  deterministicKeys,
6079
6136
  missedPipeableOpportunity,
6080
- strictEffectProvide
6137
+ strictEffectProvide,
6138
+ unknownInEffectCatch
6081
6139
  ];
6082
6140
 
6083
6141
  // src/transform.ts