@effect/language-service 0.66.1 → 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/index.js CHANGED
@@ -8467,9 +8467,20 @@ var effectFnOpportunity = createDiagnostic({
8467
8467
  if (!traceName) return yield* TypeParserIssue.issue;
8468
8468
  const opportunity = yield* pipe(
8469
8469
  tryParseGenOpportunity(node),
8470
- orElse2(
8471
- () => succeed({ effectModuleName: sourceEffectModuleName, pipeArguments: [], generatorFunction: void 0 })
8472
- )
8470
+ orElse2(() => {
8471
+ if (ts.isArrowFunction(node) && !ts.isBlock(node.body)) {
8472
+ return TypeParserIssue.issue;
8473
+ }
8474
+ const body = ts.isArrowFunction(node) ? node.body : node.body;
8475
+ if (!body || !ts.isBlock(body) || body.statements.length <= 5) {
8476
+ return TypeParserIssue.issue;
8477
+ }
8478
+ return succeed({
8479
+ effectModuleName: sourceEffectModuleName,
8480
+ pipeArguments: [],
8481
+ generatorFunction: void 0
8482
+ });
8483
+ })
8473
8484
  );
8474
8485
  return {
8475
8486
  node,
@@ -9081,6 +9092,69 @@ var importFromBarrel = createDiagnostic({
9081
9092
  })
9082
9093
  });
9083
9094
 
9095
+ // src/diagnostics/instanceOfSchema.ts
9096
+ var instanceOfSchema = createDiagnostic({
9097
+ name: "instanceOfSchema",
9098
+ code: 45,
9099
+ description: "Suggests using Schema.is instead of instanceof for Effect Schema types",
9100
+ severity: "off",
9101
+ apply: fn("instanceOfSchema.apply")(function* (sourceFile, report) {
9102
+ const ts = yield* service(TypeScriptApi);
9103
+ const typeParser = yield* service(TypeParser);
9104
+ const typeCheckerUtils = yield* service(TypeCheckerUtils);
9105
+ const nodeToVisit = [];
9106
+ const appendNodeToVisit = (node) => {
9107
+ nodeToVisit.push(node);
9108
+ return void 0;
9109
+ };
9110
+ ts.forEachChild(sourceFile, appendNodeToVisit);
9111
+ while (nodeToVisit.length > 0) {
9112
+ const node = nodeToVisit.shift();
9113
+ if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.InstanceOfKeyword) {
9114
+ const leftExpr = node.left;
9115
+ const rightExpr = node.right;
9116
+ const rightType = typeCheckerUtils.getTypeAtLocation(rightExpr);
9117
+ if (!rightType) {
9118
+ ts.forEachChild(node, appendNodeToVisit);
9119
+ continue;
9120
+ }
9121
+ const isSchemaType = yield* pipe(
9122
+ typeParser.effectSchemaType(rightType, rightExpr),
9123
+ option
9124
+ );
9125
+ if (isSchemaType._tag === "Some") {
9126
+ report({
9127
+ location: node,
9128
+ messageText: "Consider using Schema.is instead of instanceof for Effect Schema types.",
9129
+ fixes: [{
9130
+ fixName: "instanceOfSchema_fix",
9131
+ description: "Replace with Schema.is",
9132
+ apply: gen(function* () {
9133
+ const changeTracker = yield* service(ChangeTracker);
9134
+ const schemaIsCall = ts.factory.createCallExpression(
9135
+ ts.factory.createPropertyAccessExpression(
9136
+ ts.factory.createIdentifier("Schema"),
9137
+ "is"
9138
+ ),
9139
+ void 0,
9140
+ [rightExpr]
9141
+ );
9142
+ const fullCall = ts.factory.createCallExpression(
9143
+ schemaIsCall,
9144
+ void 0,
9145
+ [leftExpr]
9146
+ );
9147
+ changeTracker.replaceNode(sourceFile, node, fullCall);
9148
+ })
9149
+ }]
9150
+ });
9151
+ }
9152
+ }
9153
+ ts.forEachChild(node, appendNodeToVisit);
9154
+ }
9155
+ })
9156
+ });
9157
+
9084
9158
  // src/diagnostics/layerMergeAllWithDependencies.ts
9085
9159
  var layerMergeAllWithDependencies = createDiagnostic({
9086
9160
  name: "layerMergeAllWithDependencies",
@@ -9288,12 +9362,18 @@ var leakingRequirements = createDiagnostic({
9288
9362
  );
9289
9363
  function reportLeakingRequirements(node, requirements) {
9290
9364
  if (requirements.length === 0) return;
9365
+ const requirementsStr = requirements.map((_) => typeChecker.typeToString(_)).join(" | ");
9291
9366
  report({
9292
9367
  location: node,
9293
- messageText: `This Service is leaking the ${requirements.map((_) => typeChecker.typeToString(_)).join(" | ")} requirement.
9294
- 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.
9295
- Services should usually be collected in the layer creation body, and then provided at each method that requires them.
9296
- More info at https://effect.website/docs/requirements-management/layers/#avoiding-requirement-leakage`,
9368
+ messageText: `Methods of this Service require \`${requirementsStr}\` from every caller.
9369
+
9370
+ 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.
9371
+
9372
+ Resolve these dependencies at Layer creation and provide them to each method, so the service's type reflects its purpose, not its implementation.
9373
+
9374
+ 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.
9375
+
9376
+ More info and examples at https://effect.website/docs/requirements-management/layers/#avoiding-requirement-leakage`,
9297
9377
  fixes: []
9298
9378
  });
9299
9379
  }
@@ -11471,6 +11551,7 @@ var unsupportedServiceAccessors = createDiagnostic({
11471
11551
  // src/diagnostics.ts
11472
11552
  var diagnostics = [
11473
11553
  anyUnknownInErrorContext,
11554
+ instanceOfSchema,
11474
11555
  catchAllToMapError,
11475
11556
  catchUnfailableEffect,
11476
11557
  classSelfMismatch,