@effect/language-service 0.29.0 → 0.31.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 CHANGED
@@ -46,10 +46,13 @@ And you're done! You'll now be able to use a set of refactors and diagnostics th
46
46
  - Warn on leaking requirements in Effect services
47
47
  - Warn on Scope as requirement of a Layer
48
48
  - Warn on subsequent `Effect.provide` anti-pattern
49
+ - Detect wrong `Self` type parameter for APIs like `Effect.Service` or `Schema.TaggedError` and similar 
49
50
  - Unnecessary usages of `Effect.gen` or `pipe()`
50
51
  - Warn when importing from a barrel file instead of from the module directly
51
52
  - Warn on usage of try/catch inside `Effect.gen` and family
52
53
  - Detect unnecessary pipe chains like `X.pipe(Y).pipe(Z)`
54
+ - Warn when using `Effect.Service` with `accessors: true` but methods have generics or multiple signatures
55
+ - Warn on missing service dependencies in `Effect.Service` declarations
53
56
 
54
57
  ### Completions
55
58
 
@@ -106,30 +109,6 @@ Few options can be provided alongside the initialization of the Language Service
106
109
  ### DiagnosticSeverty properties list
107
110
 
108
111
  The full list can be found in the [diagnostics](https://github.com/Effect-TS/language-service/tree/main/src/diagnostics) folder.
109
- Here is the current list of diagnostics you can use to override severity:
110
-
111
-
112
- ```bash
113
- duplicatePackage
114
- effectInVoidSuccess
115
- floatingEffect
116
- genericEffectServices
117
- importFromBarrel
118
- leakingRequirements
119
- middlewareAutoImportQuickfixes
120
- missingEffectContext
121
- missingEffectError
122
- missingReturnYieldStar
123
- missingStarInYieldEffectGen
124
- multipleEffectProvide
125
- returnEffectInGen
126
- scopeInLayerEffect
127
- strictBooleanExpressions
128
- tryCatchInEffectGen
129
- unnecessaryEffectGen
130
- unnecessaryPipe
131
- unnecessaryPipeChain
132
- ```
133
112
 
134
113
  ## Why do diagnostics not appear at compile time?
135
114
 
package/cli.js CHANGED
@@ -29927,6 +29927,36 @@ function make64(ts2, tsUtils, typeChecker) {
29927
29927
  "TypeParser.effectSubtype",
29928
29928
  (type2) => type2
29929
29929
  );
29930
+ const importedSchemaModule = cachedBy(
29931
+ fn("TypeParser.importedSchemaModule")(function* (node) {
29932
+ const type2 = typeChecker.getTypeAtLocation(node);
29933
+ const propertySymbol = typeChecker.getPropertyOfType(type2, "Class");
29934
+ if (!propertySymbol) {
29935
+ return yield* typeParserIssue("Type has no 'Class' property", type2, node);
29936
+ }
29937
+ if (!ts2.isExpression(node)) {
29938
+ return yield* typeParserIssue("Node is not an expression", type2, node);
29939
+ }
29940
+ return node;
29941
+ }),
29942
+ "TypeParser.importedSchemaModule",
29943
+ (node) => node
29944
+ );
29945
+ const importedContextModule = cachedBy(
29946
+ fn("TypeParser.importedContextModule")(function* (node) {
29947
+ const type2 = typeChecker.getTypeAtLocation(node);
29948
+ const propertySymbol = typeChecker.getPropertyOfType(type2, "Tag");
29949
+ if (!propertySymbol) {
29950
+ return yield* typeParserIssue("Type has no 'Tag' property", type2, node);
29951
+ }
29952
+ if (!ts2.isExpression(node)) {
29953
+ return yield* typeParserIssue("Node is not an expression", type2, node);
29954
+ }
29955
+ return node;
29956
+ }),
29957
+ "TypeParser.importedContextModule",
29958
+ (node) => node
29959
+ );
29930
29960
  const importedEffectModule = cachedBy(
29931
29961
  fn("TypeParser.importedEffectModule")(function* (node) {
29932
29962
  const type2 = typeChecker.getTypeAtLocation(node);
@@ -30283,6 +30313,226 @@ function make64(ts2, tsUtils, typeChecker) {
30283
30313
  "TypeParser.promiseLike",
30284
30314
  (type2) => type2
30285
30315
  );
30316
+ const extendsSchemaClass = cachedBy(
30317
+ fn("TypeParser.extendsSchemaClass")(function* (atLocation) {
30318
+ if (!atLocation.name) {
30319
+ return yield* typeParserIssue("Class has no name", void 0, atLocation);
30320
+ }
30321
+ const heritageClauses = atLocation.heritageClauses;
30322
+ if (!heritageClauses) {
30323
+ return yield* typeParserIssue("Class has no heritage clauses", void 0, atLocation);
30324
+ }
30325
+ for (const heritageClause of heritageClauses) {
30326
+ for (const typeX of heritageClause.types) {
30327
+ if (ts2.isExpressionWithTypeArguments(typeX)) {
30328
+ const expression = typeX.expression;
30329
+ if (ts2.isCallExpression(expression)) {
30330
+ const schemaCall = expression.expression;
30331
+ if (ts2.isCallExpression(schemaCall) && schemaCall.typeArguments && schemaCall.typeArguments.length > 0) {
30332
+ const selfTypeNode = schemaCall.typeArguments[0];
30333
+ const schemaIdentifier = schemaCall.expression;
30334
+ if (ts2.isPropertyAccessExpression(schemaIdentifier) && ts2.isIdentifier(schemaIdentifier.name) && schemaIdentifier.name.text === "Class") {
30335
+ const parsedSchemaModule = yield* pipe(
30336
+ importedSchemaModule(schemaIdentifier.expression),
30337
+ option4
30338
+ );
30339
+ if (isSome2(parsedSchemaModule)) {
30340
+ return {
30341
+ className: atLocation.name,
30342
+ selfTypeNode,
30343
+ Schema: parsedSchemaModule.value
30344
+ };
30345
+ }
30346
+ }
30347
+ }
30348
+ }
30349
+ }
30350
+ }
30351
+ }
30352
+ return yield* typeParserIssue("Class does not extend Schema.Class", void 0, atLocation);
30353
+ }),
30354
+ "TypeParser.extendsSchemaClass",
30355
+ (atLocation) => atLocation
30356
+ );
30357
+ const extendsSchemaTaggedClass = cachedBy(
30358
+ fn("TypeParser.extendsSchemaTaggedClass")(function* (atLocation) {
30359
+ if (!atLocation.name) {
30360
+ return yield* typeParserIssue("Class has no name", void 0, atLocation);
30361
+ }
30362
+ const heritageClauses = atLocation.heritageClauses;
30363
+ if (!heritageClauses) {
30364
+ return yield* typeParserIssue("Class has no heritage clauses", void 0, atLocation);
30365
+ }
30366
+ for (const heritageClause of heritageClauses) {
30367
+ for (const typeX of heritageClause.types) {
30368
+ if (ts2.isExpressionWithTypeArguments(typeX)) {
30369
+ const expression = typeX.expression;
30370
+ if (ts2.isCallExpression(expression)) {
30371
+ const tagCall = expression.expression;
30372
+ if (ts2.isCallExpression(tagCall)) {
30373
+ const schemaCall = tagCall.expression;
30374
+ if (ts2.isCallExpression(schemaCall) && schemaCall.typeArguments && schemaCall.typeArguments.length > 0) {
30375
+ const selfTypeNode = schemaCall.typeArguments[0];
30376
+ const schemaIdentifier = schemaCall.expression;
30377
+ if (ts2.isPropertyAccessExpression(schemaIdentifier) && ts2.isIdentifier(schemaIdentifier.name) && schemaIdentifier.name.text === "TaggedClass") {
30378
+ const parsedSchemaModule = yield* pipe(
30379
+ importedSchemaModule(schemaIdentifier.expression),
30380
+ option4
30381
+ );
30382
+ if (isSome2(parsedSchemaModule)) {
30383
+ return {
30384
+ className: atLocation.name,
30385
+ selfTypeNode,
30386
+ Schema: parsedSchemaModule.value
30387
+ };
30388
+ }
30389
+ }
30390
+ }
30391
+ }
30392
+ }
30393
+ }
30394
+ }
30395
+ }
30396
+ return yield* typeParserIssue("Class does not extend Schema.TaggedClass", void 0, atLocation);
30397
+ }),
30398
+ "TypeParser.extendsSchemaTaggedClass",
30399
+ (atLocation) => atLocation
30400
+ );
30401
+ const extendsSchemaTaggedError = cachedBy(
30402
+ fn("TypeParser.extendsSchemaTaggedError")(function* (atLocation) {
30403
+ if (!atLocation.name) {
30404
+ return yield* typeParserIssue("Class has no name", void 0, atLocation);
30405
+ }
30406
+ const heritageClauses = atLocation.heritageClauses;
30407
+ if (!heritageClauses) {
30408
+ return yield* typeParserIssue("Class has no heritage clauses", void 0, atLocation);
30409
+ }
30410
+ for (const heritageClause of heritageClauses) {
30411
+ for (const typeX of heritageClause.types) {
30412
+ if (ts2.isExpressionWithTypeArguments(typeX)) {
30413
+ const expression = typeX.expression;
30414
+ if (ts2.isCallExpression(expression)) {
30415
+ const tagCall = expression.expression;
30416
+ if (ts2.isCallExpression(tagCall)) {
30417
+ const schemaCall = tagCall.expression;
30418
+ if (ts2.isCallExpression(schemaCall) && schemaCall.typeArguments && schemaCall.typeArguments.length > 0) {
30419
+ const selfTypeNode = schemaCall.typeArguments[0];
30420
+ const schemaIdentifier = schemaCall.expression;
30421
+ if (ts2.isPropertyAccessExpression(schemaIdentifier) && ts2.isIdentifier(schemaIdentifier.name) && schemaIdentifier.name.text === "TaggedError") {
30422
+ const parsedSchemaModule = yield* pipe(
30423
+ importedSchemaModule(schemaIdentifier.expression),
30424
+ option4
30425
+ );
30426
+ if (isSome2(parsedSchemaModule)) {
30427
+ return {
30428
+ className: atLocation.name,
30429
+ selfTypeNode,
30430
+ Schema: parsedSchemaModule.value
30431
+ };
30432
+ }
30433
+ }
30434
+ }
30435
+ }
30436
+ }
30437
+ }
30438
+ }
30439
+ }
30440
+ return yield* typeParserIssue("Class does not extend Schema.TaggedError", void 0, atLocation);
30441
+ }),
30442
+ "TypeParser.extendsSchemaTaggedError",
30443
+ (atLocation) => atLocation
30444
+ );
30445
+ const extendsSchemaTaggedRequest = cachedBy(
30446
+ fn("TypeParser.extendsSchemaTaggedRequest")(function* (atLocation) {
30447
+ if (!atLocation.name) {
30448
+ return yield* typeParserIssue("Class has no name", void 0, atLocation);
30449
+ }
30450
+ const heritageClauses = atLocation.heritageClauses;
30451
+ if (!heritageClauses) {
30452
+ return yield* typeParserIssue("Class has no heritage clauses", void 0, atLocation);
30453
+ }
30454
+ for (const heritageClause of heritageClauses) {
30455
+ for (const typeX of heritageClause.types) {
30456
+ if (ts2.isExpressionWithTypeArguments(typeX)) {
30457
+ const expression = typeX.expression;
30458
+ if (ts2.isCallExpression(expression)) {
30459
+ const tagCall = expression.expression;
30460
+ if (ts2.isCallExpression(tagCall)) {
30461
+ const schemaCall = tagCall.expression;
30462
+ if (ts2.isCallExpression(schemaCall) && schemaCall.typeArguments && schemaCall.typeArguments.length > 0) {
30463
+ const selfTypeNode = schemaCall.typeArguments[0];
30464
+ const schemaIdentifier = schemaCall.expression;
30465
+ if (ts2.isPropertyAccessExpression(schemaIdentifier) && ts2.isIdentifier(schemaIdentifier.name) && schemaIdentifier.name.text === "TaggedRequest") {
30466
+ const parsedSchemaModule = yield* pipe(
30467
+ importedSchemaModule(schemaIdentifier.expression),
30468
+ option4
30469
+ );
30470
+ if (isSome2(parsedSchemaModule)) {
30471
+ return {
30472
+ className: atLocation.name,
30473
+ selfTypeNode,
30474
+ Schema: parsedSchemaModule.value
30475
+ };
30476
+ }
30477
+ }
30478
+ }
30479
+ }
30480
+ }
30481
+ }
30482
+ }
30483
+ }
30484
+ return yield* typeParserIssue("Class does not extend Schema.TaggedRequest", void 0, atLocation);
30485
+ }),
30486
+ "TypeParser.extendsSchemaTaggedRequest",
30487
+ (atLocation) => atLocation
30488
+ );
30489
+ const extendsContextTag = cachedBy(
30490
+ fn("TypeParser.extendsContextTag")(function* (atLocation) {
30491
+ if (!atLocation.name) {
30492
+ return yield* typeParserIssue("Class has no name", void 0, atLocation);
30493
+ }
30494
+ const classSym = typeChecker.getSymbolAtLocation(atLocation.name);
30495
+ if (!classSym) return yield* typeParserIssue("Class has no symbol", void 0, atLocation);
30496
+ const type2 = typeChecker.getTypeOfSymbol(classSym);
30497
+ const heritageClauses = atLocation.heritageClauses;
30498
+ if (!heritageClauses) {
30499
+ return yield* typeParserIssue("Class has no heritage clauses", void 0, atLocation);
30500
+ }
30501
+ for (const heritageClause of heritageClauses) {
30502
+ for (const typeX of heritageClause.types) {
30503
+ if (ts2.isExpressionWithTypeArguments(typeX)) {
30504
+ const wholeCall = typeX.expression;
30505
+ if (ts2.isCallExpression(wholeCall)) {
30506
+ const contextTagCall = wholeCall.expression;
30507
+ if (ts2.isCallExpression(contextTagCall) && wholeCall.typeArguments && wholeCall.typeArguments.length > 0) {
30508
+ const contextTagIdentifier = contextTagCall.expression;
30509
+ const selfTypeNode = wholeCall.typeArguments[0];
30510
+ if (ts2.isPropertyAccessExpression(contextTagIdentifier) && ts2.isIdentifier(contextTagIdentifier.name) && contextTagIdentifier.name.text === "Tag") {
30511
+ const parsedContextModule = yield* pipe(
30512
+ importedContextModule(contextTagIdentifier.expression),
30513
+ option4
30514
+ );
30515
+ if (isSome2(parsedContextModule)) {
30516
+ const tagType = yield* contextTag(type2, atLocation);
30517
+ return {
30518
+ className: atLocation.name,
30519
+ selfTypeNode,
30520
+ args: contextTagCall.arguments,
30521
+ Identifier: tagType.Identifier,
30522
+ Tag: parsedContextModule.value
30523
+ };
30524
+ }
30525
+ }
30526
+ }
30527
+ }
30528
+ }
30529
+ }
30530
+ }
30531
+ return yield* typeParserIssue("Class does not extend Context.Tag", void 0, atLocation);
30532
+ }),
30533
+ "TypeParser.extendsContextTag",
30534
+ (atLocation) => atLocation
30535
+ );
30286
30536
  const extendsEffectService = cachedBy(
30287
30537
  fn("TypeParser.extendsEffectService")(function* (atLocation) {
30288
30538
  if (!atLocation.name) {
@@ -30312,6 +30562,7 @@ function make64(ts2, tsUtils, typeChecker) {
30312
30562
  );
30313
30563
  if (isSome2(parsedContextTag)) {
30314
30564
  let accessors2 = void 0;
30565
+ let dependencies = void 0;
30315
30566
  if (wholeCall.arguments.length >= 2) {
30316
30567
  const args3 = wholeCall.arguments[1];
30317
30568
  if (ts2.isObjectLiteralExpression(args3)) {
@@ -30319,6 +30570,9 @@ function make64(ts2, tsUtils, typeChecker) {
30319
30570
  if (ts2.isPropertyAssignment(property) && property.name && ts2.isIdentifier(property.name) && property.name.text === "accessors" && property.initializer && property.initializer.kind === ts2.SyntaxKind.TrueKeyword) {
30320
30571
  accessors2 = true;
30321
30572
  }
30573
+ if (ts2.isPropertyAssignment(property) && property.name && ts2.isIdentifier(property.name) && property.name.text === "dependencies" && property.initializer && ts2.isArrayLiteralExpression(property.initializer)) {
30574
+ dependencies = property.initializer.elements;
30575
+ }
30322
30576
  }
30323
30577
  }
30324
30578
  }
@@ -30327,7 +30581,8 @@ function make64(ts2, tsUtils, typeChecker) {
30327
30581
  className: atLocation.name,
30328
30582
  selfTypeNode,
30329
30583
  args: wholeCall.arguments,
30330
- accessors: accessors2
30584
+ accessors: accessors2,
30585
+ dependencies
30331
30586
  };
30332
30587
  }
30333
30588
  }
@@ -30358,10 +30613,78 @@ function make64(ts2, tsUtils, typeChecker) {
30358
30613
  pipeCall,
30359
30614
  scopeType,
30360
30615
  promiseLike,
30361
- extendsEffectService
30616
+ extendsEffectService,
30617
+ extendsContextTag,
30618
+ extendsSchemaClass,
30619
+ extendsSchemaTaggedClass,
30620
+ extendsSchemaTaggedError,
30621
+ extendsSchemaTaggedRequest
30362
30622
  };
30363
30623
  }
30364
30624
 
30625
+ // src/diagnostics/classSelfMismatch.ts
30626
+ var classSelfMismatch = createDiagnostic({
30627
+ name: "classSelfMismatch",
30628
+ code: 20,
30629
+ severity: "error",
30630
+ apply: fn("classSelfMismatch.apply")(function* (sourceFile, report) {
30631
+ const ts2 = yield* service2(TypeScriptApi);
30632
+ const typeParser = yield* service2(TypeParser);
30633
+ const nodeToVisit = [];
30634
+ const appendNodeToVisit = (node) => {
30635
+ nodeToVisit.push(node);
30636
+ return void 0;
30637
+ };
30638
+ ts2.forEachChild(sourceFile, appendNodeToVisit);
30639
+ while (nodeToVisit.length > 0) {
30640
+ const node = nodeToVisit.shift();
30641
+ if (ts2.isClassDeclaration(node) && node.name && node.heritageClauses) {
30642
+ const result = yield* pipe(
30643
+ typeParser.extendsEffectService(node),
30644
+ orElse14(() => typeParser.extendsContextTag(node)),
30645
+ orElse14(() => typeParser.extendsSchemaClass(node)),
30646
+ orElse14(() => typeParser.extendsSchemaTaggedClass(node)),
30647
+ orElse14(() => typeParser.extendsSchemaTaggedError(node)),
30648
+ orElse14(() => typeParser.extendsSchemaTaggedRequest(node)),
30649
+ orElse14(() => void_8)
30650
+ );
30651
+ if (result) {
30652
+ const { className, selfTypeNode } = result;
30653
+ let actualName = "";
30654
+ if (ts2.isTypeReferenceNode(selfTypeNode)) {
30655
+ if (ts2.isIdentifier(selfTypeNode.typeName)) {
30656
+ actualName = selfTypeNode.typeName.text;
30657
+ } else if (ts2.isQualifiedName(selfTypeNode.typeName)) {
30658
+ actualName = selfTypeNode.typeName.right.text;
30659
+ }
30660
+ }
30661
+ const expectedName = className.text;
30662
+ if (actualName !== expectedName) {
30663
+ report({
30664
+ location: selfTypeNode,
30665
+ messageText: `Self type parameter should be '${expectedName}'`,
30666
+ fixes: [{
30667
+ fixName: "classSelfMismatch_fix",
30668
+ description: `Replace '${actualName}' with '${expectedName}'`,
30669
+ apply: gen3(function* () {
30670
+ const changeTracker = yield* service2(ChangeTracker);
30671
+ const typeArgs = ts2.isTypeReferenceNode(selfTypeNode) ? selfTypeNode.typeArguments : void 0;
30672
+ const newTypeReference = ts2.factory.createTypeReferenceNode(
30673
+ ts2.factory.createIdentifier(expectedName),
30674
+ typeArgs
30675
+ );
30676
+ changeTracker.replaceNode(sourceFile, selfTypeNode, newTypeReference);
30677
+ })
30678
+ }]
30679
+ });
30680
+ }
30681
+ }
30682
+ }
30683
+ ts2.forEachChild(node, appendNodeToVisit);
30684
+ }
30685
+ })
30686
+ });
30687
+
30365
30688
  // src/diagnostics/duplicatePackage.ts
30366
30689
  var checkedPackagesCache = /* @__PURE__ */ new Map();
30367
30690
  var programResolvedCacheSize = /* @__PURE__ */ new Map();
@@ -30981,6 +31304,89 @@ var missingEffectError = createDiagnostic({
30981
31304
  })
30982
31305
  });
30983
31306
 
31307
+ // src/diagnostics/missingEffectServiceDependency.ts
31308
+ var missingEffectServiceDependency = createDiagnostic({
31309
+ name: "missingEffectServiceDependency",
31310
+ code: 21,
31311
+ severity: "off",
31312
+ apply: fn("missingEffectServiceDependency.apply")(function* (sourceFile, report) {
31313
+ const ts2 = yield* service2(TypeScriptApi);
31314
+ const typeChecker = yield* service2(TypeCheckerApi);
31315
+ const typeParser = yield* service2(TypeParser);
31316
+ const nodeToVisit = [];
31317
+ const appendNodeToVisit = (node) => {
31318
+ nodeToVisit.push(node);
31319
+ return void 0;
31320
+ };
31321
+ ts2.forEachChild(sourceFile, appendNodeToVisit);
31322
+ while (nodeToVisit.length > 0) {
31323
+ const node = nodeToVisit.shift();
31324
+ if (ts2.isClassDeclaration(node) && node.name && node.heritageClauses) {
31325
+ const serviceResult = yield* pipe(
31326
+ typeParser.extendsEffectService(node),
31327
+ orElse14(() => void_8)
31328
+ );
31329
+ if (serviceResult) {
31330
+ const { className, dependencies } = serviceResult;
31331
+ const classSymbol = typeChecker.getSymbolAtLocation(className);
31332
+ if (classSymbol) {
31333
+ const classType = typeChecker.getTypeOfSymbol(classSymbol);
31334
+ const defaultWithoutDepsProperty = typeChecker.getPropertyOfType(classType, "DefaultWithoutDependencies");
31335
+ const defaultProperty = defaultWithoutDepsProperty || typeChecker.getPropertyOfType(classType, "Default");
31336
+ if (defaultProperty) {
31337
+ const defaultType = typeChecker.getTypeOfSymbolAtLocation(defaultProperty, node);
31338
+ const layerResult = yield* pipe(
31339
+ typeParser.layerType(defaultType, node),
31340
+ orElse14(() => void_8)
31341
+ );
31342
+ if (layerResult) {
31343
+ const servicesMemory = /* @__PURE__ */ new Map();
31344
+ const excludeNever = (type2) => succeed17((type2.flags & ts2.TypeFlags.Never) !== 0);
31345
+ const { allIndexes: requiredIndexes } = yield* appendToUniqueTypesMap(
31346
+ servicesMemory,
31347
+ layerResult.RIn,
31348
+ excludeNever
31349
+ );
31350
+ const providedIndexes = /* @__PURE__ */ new Set();
31351
+ const dependenciesToProcess = dependencies || [];
31352
+ for (const depExpression of dependenciesToProcess) {
31353
+ const depType = typeChecker.getTypeAtLocation(depExpression);
31354
+ const depLayerResult = yield* pipe(
31355
+ typeParser.layerType(depType, depExpression),
31356
+ orElse14(() => void_8)
31357
+ );
31358
+ if (depLayerResult) {
31359
+ const { allIndexes } = yield* appendToUniqueTypesMap(
31360
+ servicesMemory,
31361
+ depLayerResult.ROut,
31362
+ excludeNever
31363
+ );
31364
+ for (const index of allIndexes) {
31365
+ providedIndexes.add(index);
31366
+ }
31367
+ }
31368
+ }
31369
+ const missingIndexes = requiredIndexes.filter((index) => !providedIndexes.has(index));
31370
+ if (missingIndexes.length > 0) {
31371
+ const missingTypes = missingIndexes.map((index) => servicesMemory.get(index));
31372
+ const missingTypeNames = missingTypes.map((t) => typeChecker.typeToString(t));
31373
+ const message = missingTypeNames.length === 1 ? `Service '${missingTypeNames[0]}' is required but not provided by dependencies` : `Services ${missingTypeNames.map((s) => `'${s}'`).join(", ")} are required but not provided by dependencies`;
31374
+ report({
31375
+ location: className,
31376
+ messageText: message,
31377
+ fixes: []
31378
+ });
31379
+ }
31380
+ }
31381
+ }
31382
+ }
31383
+ }
31384
+ }
31385
+ ts2.forEachChild(node, appendNodeToVisit);
31386
+ }
31387
+ })
31388
+ });
31389
+
30984
31390
  // src/diagnostics/missingReturnYieldStar.ts
30985
31391
  var missingReturnYieldStar = createDiagnostic({
30986
31392
  name: "missingReturnYieldStar",
@@ -31976,11 +32382,68 @@ var unnecessaryPipeChain = createDiagnostic({
31976
32382
  })
31977
32383
  });
31978
32384
 
32385
+ // src/diagnostics/unsupportedServiceAccessors.ts
32386
+ var unsupportedServiceAccessors = createDiagnostic({
32387
+ name: "unsupportedServiceAccessors",
32388
+ code: 21,
32389
+ severity: "warning",
32390
+ apply: fn("unsupportedServiceAccessors.apply")(function* (sourceFile, report) {
32391
+ const ts2 = yield* service2(TypeScriptApi);
32392
+ const nodeToVisit = [];
32393
+ const appendNodeToVisit = (node) => {
32394
+ nodeToVisit.push(node);
32395
+ return void 0;
32396
+ };
32397
+ ts2.forEachChild(sourceFile, appendNodeToVisit);
32398
+ while (nodeToVisit.length > 0) {
32399
+ const node = nodeToVisit.shift();
32400
+ ts2.forEachChild(node, appendNodeToVisit);
32401
+ if (ts2.isClassDeclaration(node)) {
32402
+ const parseResult = yield* pipe(
32403
+ parse5(node),
32404
+ orElse14(() => succeed17(null))
32405
+ );
32406
+ if (parseResult && parseResult.involvedMembers.length > 0) {
32407
+ const existingStaticMembers = /* @__PURE__ */ new Set();
32408
+ node.members?.forEach((member) => {
32409
+ if (ts2.isPropertyDeclaration(member) && member.modifiers?.some((mod) => mod.kind === ts2.SyntaxKind.StaticKeyword)) {
32410
+ if (member.name && ts2.isIdentifier(member.name)) {
32411
+ existingStaticMembers.add(member.name.text);
32412
+ }
32413
+ }
32414
+ });
32415
+ const missingMembers = parseResult.involvedMembers.filter(
32416
+ ({ property }) => !existingStaticMembers.has(property.getName())
32417
+ );
32418
+ if (missingMembers.length > 0) {
32419
+ const memberNames = missingMembers.map(({ property }) => `'${property.getName()}'`).join(", ");
32420
+ report({
32421
+ location: parseResult.className,
32422
+ messageText: `Even if accessors are enabled, accessors for ${memberNames} won't be available because the signature have generic type parameters or multiple call signatures.`,
32423
+ fixes: [{
32424
+ fixName: "unsupportedServiceAccessors_enableCodegen",
32425
+ description: "Enable accessors codegen",
32426
+ apply: gen3(function* () {
32427
+ const changeTracker = yield* service2(ChangeTracker);
32428
+ const comment = "// @effect-codegens accessors\n";
32429
+ changeTracker.insertText(sourceFile, node.getStart(sourceFile), comment);
32430
+ })
32431
+ }]
32432
+ });
32433
+ }
32434
+ }
32435
+ }
32436
+ }
32437
+ })
32438
+ });
32439
+
31979
32440
  // src/diagnostics.ts
31980
32441
  var diagnostics = [
32442
+ classSelfMismatch,
31981
32443
  duplicatePackage,
31982
32444
  missingEffectContext,
31983
32445
  missingEffectError,
32446
+ missingEffectServiceDependency,
31984
32447
  floatingEffect,
31985
32448
  missingStarInYieldEffectGen,
31986
32449
  unnecessaryEffectGen,
@@ -31996,7 +32459,8 @@ var diagnostics = [
31996
32459
  unnecessaryPipeChain,
31997
32460
  strictBooleanExpressions,
31998
32461
  multipleEffectProvide,
31999
- outdatedEffectCodegen
32462
+ outdatedEffectCodegen,
32463
+ unsupportedServiceAccessors
32000
32464
  ];
32001
32465
 
32002
32466
  // src/cli.ts