@effect/language-service 0.67.0 → 0.68.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.67.0",
3
+ "version": "0.68.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
@@ -5618,6 +5618,69 @@ var importFromBarrel = createDiagnostic({
5618
5618
  })
5619
5619
  });
5620
5620
 
5621
+ // src/diagnostics/instanceOfSchema.ts
5622
+ var instanceOfSchema = createDiagnostic({
5623
+ name: "instanceOfSchema",
5624
+ code: 45,
5625
+ description: "Suggests using Schema.is instead of instanceof for Effect Schema types",
5626
+ severity: "off",
5627
+ apply: fn("instanceOfSchema.apply")(function* (sourceFile, report) {
5628
+ const ts = yield* service(TypeScriptApi);
5629
+ const typeParser = yield* service(TypeParser);
5630
+ const typeCheckerUtils = yield* service(TypeCheckerUtils);
5631
+ const nodeToVisit = [];
5632
+ const appendNodeToVisit = (node) => {
5633
+ nodeToVisit.push(node);
5634
+ return void 0;
5635
+ };
5636
+ ts.forEachChild(sourceFile, appendNodeToVisit);
5637
+ while (nodeToVisit.length > 0) {
5638
+ const node = nodeToVisit.shift();
5639
+ if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.InstanceOfKeyword) {
5640
+ const leftExpr = node.left;
5641
+ const rightExpr = node.right;
5642
+ const rightType = typeCheckerUtils.getTypeAtLocation(rightExpr);
5643
+ if (!rightType) {
5644
+ ts.forEachChild(node, appendNodeToVisit);
5645
+ continue;
5646
+ }
5647
+ const isSchemaType = yield* pipe(
5648
+ typeParser.effectSchemaType(rightType, rightExpr),
5649
+ option
5650
+ );
5651
+ if (isSchemaType._tag === "Some") {
5652
+ report({
5653
+ location: node,
5654
+ messageText: "Consider using Schema.is instead of instanceof for Effect Schema types.",
5655
+ fixes: [{
5656
+ fixName: "instanceOfSchema_fix",
5657
+ description: "Replace with Schema.is",
5658
+ apply: gen(function* () {
5659
+ const changeTracker = yield* service(ChangeTracker);
5660
+ const schemaIsCall = ts.factory.createCallExpression(
5661
+ ts.factory.createPropertyAccessExpression(
5662
+ ts.factory.createIdentifier("Schema"),
5663
+ "is"
5664
+ ),
5665
+ void 0,
5666
+ [rightExpr]
5667
+ );
5668
+ const fullCall = ts.factory.createCallExpression(
5669
+ schemaIsCall,
5670
+ void 0,
5671
+ [leftExpr]
5672
+ );
5673
+ changeTracker.replaceNode(sourceFile, node, fullCall);
5674
+ })
5675
+ }]
5676
+ });
5677
+ }
5678
+ }
5679
+ ts.forEachChild(node, appendNodeToVisit);
5680
+ }
5681
+ })
5682
+ });
5683
+
5621
5684
  // src/diagnostics/layerMergeAllWithDependencies.ts
5622
5685
  var layerMergeAllWithDependencies = createDiagnostic({
5623
5686
  name: "layerMergeAllWithDependencies",
@@ -5825,12 +5888,18 @@ var leakingRequirements = createDiagnostic({
5825
5888
  );
5826
5889
  function reportLeakingRequirements(node, requirements) {
5827
5890
  if (requirements.length === 0) return;
5891
+ const requirementsStr = requirements.map((_) => typeChecker.typeToString(_)).join(" | ");
5828
5892
  report({
5829
5893
  location: node,
5830
- messageText: `This Service is leaking the ${requirements.map((_) => typeChecker.typeToString(_)).join(" | ")} requirement.
5831
- If these requirements cannot be cached and are expected to be provided per method invocation (e.g. HttpServerRequest), you can either safely disable this diagnostic for this line through quickfixes or mark the service declaration with a JSDoc @effect-leakable-service.
5832
- Services should usually be collected in the layer creation body, and then provided at each method that requires them.
5833
- More info at https://effect.website/docs/requirements-management/layers/#avoiding-requirement-leakage`,
5894
+ messageText: `Methods of this Service require \`${requirementsStr}\` from every caller.
5895
+
5896
+ This leaks implementation details into the service's public type \u2014 callers shouldn't need to know *how* the service works internally, only *what* it provides.
5897
+
5898
+ Resolve these dependencies at Layer creation and provide them to each method, so the service's type reflects its purpose, not its implementation.
5899
+
5900
+ To suppress this diagnostic for specific dependency types that are intentionally passed through (e.g., HttpServerRequest), add \`@effect-leakable-service\` JSDoc to their interface declarations (e.g., the \`${typeChecker.typeToString(requirements[0])}\` interface), not to this service.
5901
+
5902
+ More info and examples at https://effect.website/docs/requirements-management/layers/#avoiding-requirement-leakage`,
5834
5903
  fixes: []
5835
5904
  });
5836
5905
  }
@@ -9041,6 +9110,7 @@ var unsupportedServiceAccessors = createDiagnostic({
9041
9110
  // src/diagnostics.ts
9042
9111
  var diagnostics = [
9043
9112
  anyUnknownInErrorContext,
9113
+ instanceOfSchema,
9044
9114
  catchAllToMapError,
9045
9115
  catchUnfailableEffect,
9046
9116
  classSelfMismatch,