@effect/language-service 0.51.0 → 0.52.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
@@ -2657,9 +2657,10 @@ var nanoLayer3 = (fa) => gen(function* () {
2657
2657
  const tsUtils = yield* service(TypeScriptUtils);
2658
2658
  const typeChecker = yield* service(TypeCheckerApi);
2659
2659
  const typeCheckerUtils = yield* service(TypeCheckerUtils);
2660
+ const program = yield* service(TypeScriptProgram);
2660
2661
  return yield* pipe(
2661
2662
  fa,
2662
- provideService(TypeParser, make3(ts, tsUtils, typeChecker, typeCheckerUtils))
2663
+ provideService(TypeParser, make3(ts, tsUtils, typeChecker, typeCheckerUtils, program))
2663
2664
  );
2664
2665
  });
2665
2666
  var TypeParserIssue = class _TypeParserIssue {
@@ -2669,7 +2670,92 @@ var TypeParserIssue = class _TypeParserIssue {
2669
2670
  function typeParserIssue(_message, _type, _node) {
2670
2671
  return TypeParserIssue.issue;
2671
2672
  }
2672
- function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
2673
+ function make3(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
2674
+ const getSourceFilePackageInfo = cachedBy(
2675
+ fn("TypeParser.getSourceFilePackageInfo")(function* (sourceFile) {
2676
+ return tsUtils.resolveModuleWithPackageInfoFromSourceFile(program, sourceFile);
2677
+ }),
2678
+ `TypeParser.getSourceFilePackageInfo`,
2679
+ (sourceFile) => sourceFile
2680
+ );
2681
+ const getSourceFilesDeclaringSymbolModule = (packageName) => cachedBy(
2682
+ fn("TypeParser.getSourceFilesDeclaringSymbolModule")(function* (symbol3) {
2683
+ const result = [];
2684
+ if (!symbol3.declarations) return yield* typeParserIssue("Symbol has no declarations", void 0, void 0);
2685
+ for (const sourceFile of symbol3.declarations) {
2686
+ if (!ts.isSourceFile(sourceFile)) continue;
2687
+ const packageInfo = yield* getSourceFilePackageInfo(sourceFile);
2688
+ if (!packageInfo || packageInfo.name.toLowerCase() !== packageName.toLowerCase()) continue;
2689
+ result.push(sourceFile);
2690
+ }
2691
+ if (result.length > 0) {
2692
+ return result;
2693
+ }
2694
+ return yield* typeParserIssue(`Symbol has no source file declarations`, void 0, void 0);
2695
+ }),
2696
+ `TypeParser.getSourceFilesDeclaringSymbolModule(${packageName})`,
2697
+ (symbol3) => symbol3
2698
+ );
2699
+ const isSymbolReferenceToPackageModule = (givenSymbol, packageName, checkSourceFile) => {
2700
+ let symbol3 = givenSymbol;
2701
+ while (symbol3.flags & ts.SymbolFlags.Alias) {
2702
+ symbol3 = typeChecker.getAliasedSymbol(symbol3);
2703
+ }
2704
+ return pipe(
2705
+ getSourceFilesDeclaringSymbolModule(packageName)(symbol3),
2706
+ flatMap2(
2707
+ (sourceFiles) => firstSuccessOf(
2708
+ sourceFiles.map((_) => checkSourceFile(_))
2709
+ )
2710
+ )
2711
+ );
2712
+ };
2713
+ const isNodeReferenceToPackageModule = (givenNode, packageName, isCorrectSourceFile) => {
2714
+ const symbol3 = typeChecker.getSymbolAtLocation(givenNode);
2715
+ if (!symbol3) return typeParserIssue("Node has no symbol", void 0, givenNode);
2716
+ return isSymbolReferenceToPackageModule(symbol3, packageName, isCorrectSourceFile);
2717
+ };
2718
+ const getSourceFilesDeclaringSymbolExportedUnderPackageModule = (packageName, memberName) => cachedBy(
2719
+ fn("TypeParser.getSourceFilesDeclaringSymbolUnderPackageExportedMember")(function* (symbol3) {
2720
+ const result = [];
2721
+ if (!symbol3.declarations) return yield* typeParserIssue("Symbol has no declarations", void 0, void 0);
2722
+ for (const declaration of symbol3.declarations) {
2723
+ const sourceFile = tsUtils.getSourceFileOfNode(declaration);
2724
+ if (!sourceFile) continue;
2725
+ const packageInfo = yield* getSourceFilePackageInfo(sourceFile);
2726
+ if (!packageInfo || packageInfo.name.toLowerCase() !== packageName.toLowerCase()) continue;
2727
+ const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
2728
+ if (!moduleSymbol) continue;
2729
+ const memberSymbol = typeChecker.tryGetMemberInModuleExports(memberName, moduleSymbol);
2730
+ if (memberSymbol && memberSymbol === symbol3) result.push({ memberSymbol, moduleSymbol, sourceFile });
2731
+ }
2732
+ if (result.length > 0) {
2733
+ return result;
2734
+ }
2735
+ return yield* typeParserIssue(`Symbol has no declarations`, void 0, void 0);
2736
+ }),
2737
+ `TypeParser.getSourceFilesDeclaringSymbolUnderPackageExportedMember(${packageName}, ${memberName})`,
2738
+ (sym) => sym
2739
+ );
2740
+ const isSymbolExportOfPackageModule = (givenSymbol, packageName, memberName, checkSourceFile) => {
2741
+ let symbol3 = givenSymbol;
2742
+ while (symbol3.flags & ts.SymbolFlags.Alias) {
2743
+ symbol3 = typeChecker.getAliasedSymbol(symbol3);
2744
+ }
2745
+ return pipe(
2746
+ getSourceFilesDeclaringSymbolExportedUnderPackageModule(packageName, memberName)(symbol3),
2747
+ flatMap2(
2748
+ (sourceFiles) => firstSuccessOf(
2749
+ sourceFiles.map((_) => checkSourceFile(_.sourceFile, _.moduleSymbol, _.memberSymbol))
2750
+ )
2751
+ )
2752
+ );
2753
+ };
2754
+ const isNodeReferenceToExportOfPackageModule = (givenNode, packageName, isCorrectSourceFile, memberName) => {
2755
+ const symbol3 = typeChecker.getSymbolAtLocation(givenNode);
2756
+ if (!symbol3) return typeParserIssue("Node has no symbol", void 0, givenNode);
2757
+ return isSymbolExportOfPackageModule(symbol3, packageName, memberName, isCorrectSourceFile);
2758
+ };
2673
2759
  function covariantTypeArgument(type) {
2674
2760
  const signatures = typeChecker.getSignaturesOfType(type, ts.SignatureKind.Call);
2675
2761
  if (signatures.length !== 1) {
@@ -2775,6 +2861,26 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
2775
2861
  "TypeParser.strictEffectType",
2776
2862
  (type) => type
2777
2863
  );
2864
+ const isEffectTypeSourceFile = cachedBy(
2865
+ fn("TypeParser.isEffectTypeSourceFile")(function* (sourceFile) {
2866
+ const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
2867
+ if (!moduleSymbol) return yield* typeParserIssue("Node has no symbol", void 0, sourceFile);
2868
+ const effectTypeSymbol = typeChecker.tryGetMemberInModuleExports("Effect", moduleSymbol);
2869
+ if (!effectTypeSymbol) return yield* typeParserIssue("Effect type not found", void 0, sourceFile);
2870
+ const type = typeChecker.getDeclaredTypeOfSymbol(effectTypeSymbol);
2871
+ yield* effectType(type, sourceFile);
2872
+ return sourceFile;
2873
+ }),
2874
+ "TypeParser.isEffectTypeSourceFile",
2875
+ (sourceFile) => sourceFile
2876
+ );
2877
+ const isNodeReferenceToEffectModuleApi = (memberName) => cachedBy(
2878
+ fn("TypeParser.isNodeReferenceToEffectModuleApi")(function* (node) {
2879
+ return yield* isNodeReferenceToExportOfPackageModule(node, "effect", isEffectTypeSourceFile, memberName);
2880
+ }),
2881
+ `TypeParser.isNodeReferenceToEffectModuleApi(${memberName})`,
2882
+ (node) => node
2883
+ );
2778
2884
  const layerType = cachedBy(
2779
2885
  fn("TypeParser.layerType")(function* (type, atLocation) {
2780
2886
  yield* pipeableType(type, atLocation);
@@ -2831,36 +2937,6 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
2831
2937
  "TypeParser.effectSubtype",
2832
2938
  (type) => type
2833
2939
  );
2834
- const importedSchemaModule = cachedBy(
2835
- fn("TypeParser.importedSchemaModule")(function* (node) {
2836
- if (!ts.isIdentifier(node)) {
2837
- return yield* typeParserIssue("Node is not an expression", void 0, node);
2838
- }
2839
- const type = typeChecker.getTypeAtLocation(node);
2840
- const propertySymbol = typeChecker.getPropertyOfType(type, "Class");
2841
- if (!propertySymbol) {
2842
- return yield* typeParserIssue("Type has no 'Class' property", type, node);
2843
- }
2844
- const sourceFile = tsUtils.getSourceFileOfNode(node);
2845
- if (!sourceFile) {
2846
- return yield* typeParserIssue("Node is not in a source file", void 0, node);
2847
- }
2848
- const schemaIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
2849
- sourceFile,
2850
- "effect",
2851
- "Schema"
2852
- );
2853
- if (!schemaIdentifier) {
2854
- return yield* typeParserIssue("Schema module not found", void 0, node);
2855
- }
2856
- if (ts.idText(node) !== schemaIdentifier) {
2857
- return yield* typeParserIssue("Node is not a schema module reference", void 0, node);
2858
- }
2859
- return node;
2860
- }),
2861
- "TypeParser.importedSchemaModule",
2862
- (node) => node
2863
- );
2864
2940
  const importedContextModule = cachedBy(
2865
2941
  fn("TypeParser.importedContextModule")(function* (node) {
2866
2942
  const type = typeChecker.getTypeAtLocation(node);
@@ -2891,22 +2967,9 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
2891
2967
  "TypeParser.importedContextModule",
2892
2968
  (node) => node
2893
2969
  );
2894
- const importedEffectModule = cachedBy(
2895
- fn("TypeParser.importedEffectModule")(function* (node) {
2896
- const type = typeChecker.getTypeAtLocation(node);
2897
- const propertySymbol = typeChecker.getPropertyOfType(type, "never");
2898
- if (!propertySymbol) {
2899
- return yield* typeParserIssue("Type has no 'never' property", type, node);
2900
- }
2901
- if (!ts.isExpression(node)) {
2902
- return yield* typeParserIssue("Node is not an expression", type, node);
2903
- }
2904
- const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, node);
2905
- yield* effectType(propertyType, node);
2906
- return node;
2907
- }),
2908
- "TypeParser.importedEffectModule",
2909
- (node) => node
2970
+ const importedEffectModule = (node) => pipe(
2971
+ isNodeReferenceToPackageModule(node, "effect", isEffectTypeSourceFile),
2972
+ map5(() => node)
2910
2973
  );
2911
2974
  const importedDataModule = cachedBy(
2912
2975
  fn("TypeParser.importedDataModule")(function* (node) {
@@ -2957,14 +3020,11 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
2957
3020
  return typeParserIssue("Node is not a property access expression", void 0, node);
2958
3021
  }
2959
3022
  const propertyAccess = node.expression;
2960
- if (!(ts.isIdentifier(propertyAccess.name) && ts.idText(propertyAccess.name) === "gen")) {
2961
- return typeParserIssue("Call expression name is not 'gen'", void 0, node);
2962
- }
2963
3023
  return pipe(
2964
- importedEffectModule(propertyAccess.expression),
2965
- map5((effectModule) => ({
3024
+ isNodeReferenceToEffectModuleApi("gen")(propertyAccess),
3025
+ map5(() => ({
2966
3026
  node,
2967
- effectModule,
3027
+ effectModule: propertyAccess.expression,
2968
3028
  generatorFunction,
2969
3029
  body: generatorFunction.body
2970
3030
  }))
@@ -3000,18 +3060,11 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
3000
3060
  );
3001
3061
  }
3002
3062
  const propertyAccess = node.expression;
3003
- if (!(ts.isIdentifier(propertyAccess.name) && ts.idText(propertyAccess.name) === "fnUntraced")) {
3004
- return typeParserIssue(
3005
- "Call expression name is not 'fnUntraced'",
3006
- void 0,
3007
- node
3008
- );
3009
- }
3010
3063
  return pipe(
3011
- importedEffectModule(propertyAccess.expression),
3012
- map5((effectModule) => ({
3064
+ isNodeReferenceToEffectModuleApi("fnUntraced")(propertyAccess),
3065
+ map5(() => ({
3013
3066
  node,
3014
- effectModule,
3067
+ effectModule: propertyAccess.expression,
3015
3068
  generatorFunction,
3016
3069
  body: generatorFunction.body
3017
3070
  }))
@@ -3052,19 +3105,12 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
3052
3105
  );
3053
3106
  }
3054
3107
  const propertyAccess = expressionToTest;
3055
- if (!(ts.isIdentifier(propertyAccess.name) && ts.idText(propertyAccess.name) === "fn")) {
3056
- return typeParserIssue(
3057
- "Call expression name is not 'fn'",
3058
- void 0,
3059
- node
3060
- );
3061
- }
3062
3108
  return pipe(
3063
- importedEffectModule(propertyAccess.expression),
3064
- map5((effectModule) => ({
3109
+ isNodeReferenceToEffectModuleApi("fn")(propertyAccess),
3110
+ map5(() => ({
3065
3111
  node,
3066
3112
  generatorFunction,
3067
- effectModule,
3113
+ effectModule: propertyAccess.expression,
3068
3114
  body: generatorFunction.body
3069
3115
  }))
3070
3116
  );
@@ -3166,6 +3212,26 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
3166
3212
  "TypeParser.effectSchemaType",
3167
3213
  (type) => type
3168
3214
  );
3215
+ const isEffectSchemaTypeSourceFile = cachedBy(
3216
+ fn("TypeParser.isEffectSchemaTypeSourceFile")(function* (sourceFile) {
3217
+ const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
3218
+ if (!moduleSymbol) return yield* typeParserIssue("Node has no symbol", void 0, sourceFile);
3219
+ const typeSymbol = typeChecker.tryGetMemberInModuleExports("Schema", moduleSymbol);
3220
+ if (!typeSymbol) return yield* typeParserIssue("Schema type not found", void 0, sourceFile);
3221
+ const type = typeChecker.getDeclaredTypeOfSymbol(typeSymbol);
3222
+ yield* effectSchemaType(type, sourceFile);
3223
+ return sourceFile;
3224
+ }),
3225
+ "TypeParser.isEffectSchemaTypeSourceFile",
3226
+ (sourceFile) => sourceFile
3227
+ );
3228
+ const isNodeReferenceToEffectSchemaModuleApi = (memberName) => cachedBy(
3229
+ fn("TypeParser.isNodeReferenceToEffectSchemaModuleApi")(function* (node) {
3230
+ return yield* isNodeReferenceToExportOfPackageModule(node, "effect", isEffectSchemaTypeSourceFile, memberName);
3231
+ }),
3232
+ `TypeParser.isNodeReferenceToEffectSchemaModuleApi(${memberName})`,
3233
+ (node) => node
3234
+ );
3169
3235
  const contextTagVarianceStruct = (type, atLocation) => map5(
3170
3236
  all(
3171
3237
  varianceStructInvariantType(type, atLocation, "_Identifier"),
@@ -3292,22 +3358,15 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
3292
3358
  if (ts.isCallExpression(expression)) {
3293
3359
  const schemaCall = expression.expression;
3294
3360
  if (ts.isCallExpression(schemaCall) && schemaCall.typeArguments && schemaCall.typeArguments.length > 0) {
3295
- const selfTypeNode = schemaCall.typeArguments[0];
3296
- const schemaIdentifier = schemaCall.expression;
3297
- if (ts.isPropertyAccessExpression(schemaIdentifier) && ts.isIdentifier(schemaIdentifier.name) && ts.idText(schemaIdentifier.name) === "Class") {
3298
- const expressionType = typeChecker.getTypeAtLocation(expression);
3299
- const parsedSchemaModule = yield* pipe(
3300
- effectSchemaType(expressionType, expression),
3301
- flatMap2(() => importedSchemaModule(schemaIdentifier.expression)),
3302
- option
3303
- );
3304
- if (isSome2(parsedSchemaModule)) {
3305
- return {
3306
- className: atLocation.name,
3307
- selfTypeNode,
3308
- Schema: parsedSchemaModule.value
3309
- };
3310
- }
3361
+ const isEffectSchemaModuleApi = yield* pipe(
3362
+ isNodeReferenceToEffectSchemaModuleApi("Class")(schemaCall.expression),
3363
+ option
3364
+ );
3365
+ if (isSome2(isEffectSchemaModuleApi)) {
3366
+ return {
3367
+ className: atLocation.name,
3368
+ selfTypeNode: schemaCall.typeArguments[0]
3369
+ };
3311
3370
  }
3312
3371
  }
3313
3372
  }
@@ -3336,23 +3395,17 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
3336
3395
  const schemaTaggedClassTCall = expression.expression;
3337
3396
  if (ts.isCallExpression(schemaTaggedClassTCall) && schemaTaggedClassTCall.typeArguments && schemaTaggedClassTCall.typeArguments.length > 0) {
3338
3397
  const selfTypeNode = schemaTaggedClassTCall.typeArguments[0];
3339
- const schemaIdentifier = schemaTaggedClassTCall.expression;
3340
- if (ts.isPropertyAccessExpression(schemaIdentifier) && ts.isIdentifier(schemaIdentifier.name) && ts.idText(schemaIdentifier.name) === "TaggedClass") {
3341
- const expressionType = typeChecker.getTypeAtLocation(expression);
3342
- const parsedSchemaModule = yield* pipe(
3343
- effectSchemaType(expressionType, expression),
3344
- flatMap2(() => importedSchemaModule(schemaIdentifier.expression)),
3345
- option
3346
- );
3347
- if (isSome2(parsedSchemaModule)) {
3348
- return {
3349
- className: atLocation.name,
3350
- selfTypeNode,
3351
- keyStringLiteral: schemaTaggedClassTCall.arguments.length > 0 && ts.isStringLiteral(schemaTaggedClassTCall.arguments[0]) ? schemaTaggedClassTCall.arguments[0] : void 0,
3352
- tagStringLiteral: expression.arguments.length > 0 && ts.isStringLiteral(expression.arguments[0]) ? expression.arguments[0] : void 0,
3353
- Schema: parsedSchemaModule.value
3354
- };
3355
- }
3398
+ const isEffectSchemaModuleApi = yield* pipe(
3399
+ isNodeReferenceToEffectSchemaModuleApi("TaggedClass")(schemaTaggedClassTCall.expression),
3400
+ option
3401
+ );
3402
+ if (isSome2(isEffectSchemaModuleApi)) {
3403
+ return {
3404
+ className: atLocation.name,
3405
+ selfTypeNode,
3406
+ keyStringLiteral: schemaTaggedClassTCall.arguments.length > 0 && ts.isStringLiteral(schemaTaggedClassTCall.arguments[0]) ? schemaTaggedClassTCall.arguments[0] : void 0,
3407
+ tagStringLiteral: expression.arguments.length > 0 && ts.isStringLiteral(expression.arguments[0]) ? expression.arguments[0] : void 0
3408
+ };
3356
3409
  }
3357
3410
  }
3358
3411
  }
@@ -3381,23 +3434,17 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
3381
3434
  const schemaTaggedErrorTCall = expression.expression;
3382
3435
  if (ts.isCallExpression(schemaTaggedErrorTCall) && schemaTaggedErrorTCall.typeArguments && schemaTaggedErrorTCall.typeArguments.length > 0) {
3383
3436
  const selfTypeNode = schemaTaggedErrorTCall.typeArguments[0];
3384
- const schemaIdentifier = schemaTaggedErrorTCall.expression;
3385
- if (ts.isPropertyAccessExpression(schemaIdentifier) && ts.isIdentifier(schemaIdentifier.name) && ts.idText(schemaIdentifier.name) === "TaggedError") {
3386
- const expressionType = typeChecker.getTypeAtLocation(expression);
3387
- const parsedSchemaModule = yield* pipe(
3388
- effectSchemaType(expressionType, expression),
3389
- flatMap2(() => importedSchemaModule(schemaIdentifier.expression)),
3390
- option
3391
- );
3392
- if (isSome2(parsedSchemaModule)) {
3393
- return {
3394
- className: atLocation.name,
3395
- selfTypeNode,
3396
- keyStringLiteral: schemaTaggedErrorTCall.arguments.length > 0 && ts.isStringLiteral(schemaTaggedErrorTCall.arguments[0]) ? schemaTaggedErrorTCall.arguments[0] : void 0,
3397
- tagStringLiteral: expression.arguments.length > 0 && ts.isStringLiteral(expression.arguments[0]) ? expression.arguments[0] : void 0,
3398
- Schema: parsedSchemaModule.value
3399
- };
3400
- }
3437
+ const isEffectSchemaModuleApi = yield* pipe(
3438
+ isNodeReferenceToEffectSchemaModuleApi("TaggedError")(schemaTaggedErrorTCall.expression),
3439
+ option
3440
+ );
3441
+ if (isSome2(isEffectSchemaModuleApi)) {
3442
+ return {
3443
+ className: atLocation.name,
3444
+ selfTypeNode,
3445
+ keyStringLiteral: schemaTaggedErrorTCall.arguments.length > 0 && ts.isStringLiteral(schemaTaggedErrorTCall.arguments[0]) ? schemaTaggedErrorTCall.arguments[0] : void 0,
3446
+ tagStringLiteral: expression.arguments.length > 0 && ts.isStringLiteral(expression.arguments[0]) ? expression.arguments[0] : void 0
3447
+ };
3401
3448
  }
3402
3449
  }
3403
3450
  }
@@ -3409,8 +3456,8 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
3409
3456
  "TypeParser.extendsSchemaTaggedError",
3410
3457
  (atLocation) => atLocation
3411
3458
  );
3412
- const extendsDataTaggedError = cachedBy(
3413
- fn("TypeParser.extendsDataTaggedError")(function* (atLocation) {
3459
+ const extendsSchemaTaggedRequest = cachedBy(
3460
+ fn("TypeParser.extendsSchemaTaggedRequest")(function* (atLocation) {
3414
3461
  if (!atLocation.name) {
3415
3462
  return yield* typeParserIssue("Class has no name", void 0, atLocation);
3416
3463
  }
@@ -3423,18 +3470,19 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
3423
3470
  if (ts.isExpressionWithTypeArguments(typeX)) {
3424
3471
  const expression = typeX.expression;
3425
3472
  if (ts.isCallExpression(expression)) {
3426
- const dataTaggedErrorCall = expression;
3427
- const dataIdentifier = dataTaggedErrorCall.expression;
3428
- if (ts.isPropertyAccessExpression(dataIdentifier) && ts.isIdentifier(dataIdentifier.name) && ts.idText(dataIdentifier.name) === "TaggedError") {
3429
- const parsedDataModule = yield* pipe(
3430
- importedDataModule(dataIdentifier.expression),
3473
+ const schemaTaggedRequestTCall = expression.expression;
3474
+ if (ts.isCallExpression(schemaTaggedRequestTCall) && schemaTaggedRequestTCall.typeArguments && schemaTaggedRequestTCall.typeArguments.length > 0) {
3475
+ const selfTypeNode = schemaTaggedRequestTCall.typeArguments[0];
3476
+ const isEffectSchemaModuleApi = yield* pipe(
3477
+ isNodeReferenceToEffectSchemaModuleApi("TaggedRequest")(schemaTaggedRequestTCall.expression),
3431
3478
  option
3432
3479
  );
3433
- if (isSome2(parsedDataModule)) {
3480
+ if (isSome2(isEffectSchemaModuleApi)) {
3434
3481
  return {
3435
3482
  className: atLocation.name,
3436
- keyStringLiteral: dataTaggedErrorCall.arguments.length > 0 && ts.isStringLiteral(dataTaggedErrorCall.arguments[0]) ? dataTaggedErrorCall.arguments[0] : void 0,
3437
- Data: parsedDataModule.value
3483
+ selfTypeNode,
3484
+ tagStringLiteral: expression.arguments.length > 0 && ts.isStringLiteral(expression.arguments[0]) ? expression.arguments[0] : void 0,
3485
+ keyStringLiteral: schemaTaggedRequestTCall.arguments.length > 0 && ts.isStringLiteral(schemaTaggedRequestTCall.arguments[0]) ? schemaTaggedRequestTCall.arguments[0] : void 0
3438
3486
  };
3439
3487
  }
3440
3488
  }
@@ -3442,13 +3490,13 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
3442
3490
  }
3443
3491
  }
3444
3492
  }
3445
- return yield* typeParserIssue("Class does not extend Data.TaggedError", void 0, atLocation);
3493
+ return yield* typeParserIssue("Class does not extend Schema.TaggedRequest", void 0, atLocation);
3446
3494
  }),
3447
- "TypeParser.extendsDataTaggedError",
3495
+ "TypeParser.extendsSchemaTaggedRequest",
3448
3496
  (atLocation) => atLocation
3449
3497
  );
3450
- const extendsDataTaggedClass = cachedBy(
3451
- fn("TypeParser.extendsDataTaggedClass")(function* (atLocation) {
3498
+ const extendsDataTaggedError = cachedBy(
3499
+ fn("TypeParser.extendsDataTaggedError")(function* (atLocation) {
3452
3500
  if (!atLocation.name) {
3453
3501
  return yield* typeParserIssue("Class has no name", void 0, atLocation);
3454
3502
  }
@@ -3461,9 +3509,9 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
3461
3509
  if (ts.isExpressionWithTypeArguments(typeX)) {
3462
3510
  const expression = typeX.expression;
3463
3511
  if (ts.isCallExpression(expression)) {
3464
- const dataTaggedClassCall = expression;
3465
- const dataIdentifier = dataTaggedClassCall.expression;
3466
- if (ts.isPropertyAccessExpression(dataIdentifier) && ts.isIdentifier(dataIdentifier.name) && ts.idText(dataIdentifier.name) === "TaggedClass") {
3512
+ const dataTaggedErrorCall = expression;
3513
+ const dataIdentifier = dataTaggedErrorCall.expression;
3514
+ if (ts.isPropertyAccessExpression(dataIdentifier) && ts.isIdentifier(dataIdentifier.name) && ts.idText(dataIdentifier.name) === "TaggedError") {
3467
3515
  const parsedDataModule = yield* pipe(
3468
3516
  importedDataModule(dataIdentifier.expression),
3469
3517
  option
@@ -3471,7 +3519,7 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
3471
3519
  if (isSome2(parsedDataModule)) {
3472
3520
  return {
3473
3521
  className: atLocation.name,
3474
- keyStringLiteral: dataTaggedClassCall.arguments.length > 0 && ts.isStringLiteral(dataTaggedClassCall.arguments[0]) ? dataTaggedClassCall.arguments[0] : void 0,
3522
+ keyStringLiteral: dataTaggedErrorCall.arguments.length > 0 && ts.isStringLiteral(dataTaggedErrorCall.arguments[0]) ? dataTaggedErrorCall.arguments[0] : void 0,
3475
3523
  Data: parsedDataModule.value
3476
3524
  };
3477
3525
  }
@@ -3480,13 +3528,13 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
3480
3528
  }
3481
3529
  }
3482
3530
  }
3483
- return yield* typeParserIssue("Class does not extend Data.TaggedClass", void 0, atLocation);
3531
+ return yield* typeParserIssue("Class does not extend Data.TaggedError", void 0, atLocation);
3484
3532
  }),
3485
- "TypeParser.extendsDataTaggedClass",
3533
+ "TypeParser.extendsDataTaggedError",
3486
3534
  (atLocation) => atLocation
3487
3535
  );
3488
- const extendsSchemaTaggedRequest = cachedBy(
3489
- fn("TypeParser.extendsSchemaTaggedRequest")(function* (atLocation) {
3536
+ const extendsDataTaggedClass = cachedBy(
3537
+ fn("TypeParser.extendsDataTaggedClass")(function* (atLocation) {
3490
3538
  if (!atLocation.name) {
3491
3539
  return yield* typeParserIssue("Class has no name", void 0, atLocation);
3492
3540
  }
@@ -3499,35 +3547,28 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
3499
3547
  if (ts.isExpressionWithTypeArguments(typeX)) {
3500
3548
  const expression = typeX.expression;
3501
3549
  if (ts.isCallExpression(expression)) {
3502
- const schemaTaggedRequestTCall = expression.expression;
3503
- if (ts.isCallExpression(schemaTaggedRequestTCall) && schemaTaggedRequestTCall.typeArguments && schemaTaggedRequestTCall.typeArguments.length > 0) {
3504
- const selfTypeNode = schemaTaggedRequestTCall.typeArguments[0];
3505
- const schemaIdentifier = schemaTaggedRequestTCall.expression;
3506
- if (ts.isPropertyAccessExpression(schemaIdentifier) && ts.isIdentifier(schemaIdentifier.name) && ts.idText(schemaIdentifier.name) === "TaggedRequest") {
3507
- const expressionType = typeChecker.getTypeAtLocation(expression);
3508
- const parsedSchemaModule = yield* pipe(
3509
- effectSchemaType(expressionType, expression),
3510
- flatMap2(() => importedSchemaModule(schemaIdentifier.expression)),
3511
- option
3512
- );
3513
- if (isSome2(parsedSchemaModule)) {
3514
- return {
3515
- className: atLocation.name,
3516
- selfTypeNode,
3517
- tagStringLiteral: expression.arguments.length > 0 && ts.isStringLiteral(expression.arguments[0]) ? expression.arguments[0] : void 0,
3518
- keyStringLiteral: schemaTaggedRequestTCall.arguments.length > 0 && ts.isStringLiteral(schemaTaggedRequestTCall.arguments[0]) ? schemaTaggedRequestTCall.arguments[0] : void 0,
3519
- Schema: parsedSchemaModule.value
3520
- };
3521
- }
3550
+ const dataTaggedClassCall = expression;
3551
+ const dataIdentifier = dataTaggedClassCall.expression;
3552
+ if (ts.isPropertyAccessExpression(dataIdentifier) && ts.isIdentifier(dataIdentifier.name) && ts.idText(dataIdentifier.name) === "TaggedClass") {
3553
+ const parsedDataModule = yield* pipe(
3554
+ importedDataModule(dataIdentifier.expression),
3555
+ option
3556
+ );
3557
+ if (isSome2(parsedDataModule)) {
3558
+ return {
3559
+ className: atLocation.name,
3560
+ keyStringLiteral: dataTaggedClassCall.arguments.length > 0 && ts.isStringLiteral(dataTaggedClassCall.arguments[0]) ? dataTaggedClassCall.arguments[0] : void 0,
3561
+ Data: parsedDataModule.value
3562
+ };
3522
3563
  }
3523
3564
  }
3524
3565
  }
3525
3566
  }
3526
3567
  }
3527
3568
  }
3528
- return yield* typeParserIssue("Class does not extend Schema.TaggedRequest", void 0, atLocation);
3569
+ return yield* typeParserIssue("Class does not extend Data.TaggedClass", void 0, atLocation);
3529
3570
  }),
3530
- "TypeParser.extendsSchemaTaggedRequest",
3571
+ "TypeParser.extendsDataTaggedClass",
3531
3572
  (atLocation) => atLocation
3532
3573
  );
3533
3574
  const extendsContextTag = cachedBy(
@@ -3587,6 +3628,10 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
3587
3628
  if (!heritageClauses) {
3588
3629
  return yield* typeParserIssue("Class has no heritage clauses", void 0, atLocation);
3589
3630
  }
3631
+ const classSym = typeChecker.getSymbolAtLocation(atLocation.name);
3632
+ if (!classSym) return yield* typeParserIssue("Class has no symbol", void 0, atLocation);
3633
+ const type = typeChecker.getTypeOfSymbol(classSym);
3634
+ const tagType = yield* contextTag(type, atLocation);
3590
3635
  for (const heritageClause of heritageClauses) {
3591
3636
  for (const typeX of heritageClause.types) {
3592
3637
  if (ts.isExpressionWithTypeArguments(typeX)) {
@@ -3596,26 +3641,19 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
3596
3641
  if (ts.isCallExpression(effectTagCall) && wholeCall.typeArguments && wholeCall.typeArguments.length > 0) {
3597
3642
  const effectTagIdentifier = effectTagCall.expression;
3598
3643
  const selfTypeNode = wholeCall.typeArguments[0];
3599
- if (ts.isPropertyAccessExpression(effectTagIdentifier) && ts.isIdentifier(effectTagIdentifier.name) && ts.idText(effectTagIdentifier.name) === "Tag") {
3600
- const parsedEffectModule = yield* pipe(
3601
- importedEffectModule(effectTagIdentifier.expression),
3602
- option
3603
- );
3604
- if (isSome2(parsedEffectModule)) {
3605
- const classSym = typeChecker.getSymbolAtLocation(atLocation.name);
3606
- if (!classSym) return yield* typeParserIssue("Class has no symbol", void 0, atLocation);
3607
- const type = typeChecker.getTypeOfSymbol(classSym);
3608
- const tagType = yield* contextTag(type, atLocation);
3609
- return {
3610
- className: atLocation.name,
3611
- selfTypeNode,
3612
- keyStringLiteral: ts.isStringLiteral(effectTagCall.arguments[0]) ? effectTagCall.arguments[0] : void 0,
3613
- args: effectTagCall.arguments,
3614
- Identifier: tagType.Identifier,
3615
- Service: tagType.Service,
3616
- Tag: parsedEffectModule.value
3617
- };
3618
- }
3644
+ const isEffectTag = yield* pipe(
3645
+ isNodeReferenceToEffectModuleApi("Tag")(effectTagIdentifier),
3646
+ option
3647
+ );
3648
+ if (isSome2(isEffectTag)) {
3649
+ return {
3650
+ className: atLocation.name,
3651
+ selfTypeNode,
3652
+ keyStringLiteral: ts.isStringLiteral(effectTagCall.arguments[0]) ? effectTagCall.arguments[0] : void 0,
3653
+ args: effectTagCall.arguments,
3654
+ Identifier: tagType.Identifier,
3655
+ Service: tagType.Service
3656
+ };
3619
3657
  }
3620
3658
  }
3621
3659
  }
@@ -3645,13 +3683,16 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
3645
3683
  if (ts.isCallExpression(effectServiceCall) && effectServiceCall.typeArguments && effectServiceCall.typeArguments.length > 0) {
3646
3684
  const effectServiceIdentifier = effectServiceCall.expression;
3647
3685
  const selfTypeNode = effectServiceCall.typeArguments[0];
3648
- if (ts.isPropertyAccessExpression(effectServiceIdentifier) && ts.isIdentifier(effectServiceIdentifier.name) && ts.idText(effectServiceIdentifier.name) === "Service") {
3686
+ const isEffectService = yield* pipe(
3687
+ isNodeReferenceToEffectModuleApi("Service")(effectServiceIdentifier),
3688
+ option
3689
+ );
3690
+ if (isSome2(isEffectService)) {
3649
3691
  const classSym = typeChecker.getSymbolAtLocation(atLocation.name);
3650
3692
  if (!classSym) return yield* typeParserIssue("Class has no symbol", void 0, atLocation);
3651
3693
  const type = typeChecker.getTypeOfSymbol(classSym);
3652
3694
  const parsedContextTag = yield* pipe(
3653
- importedEffectModule(effectServiceIdentifier.expression),
3654
- flatMap2(() => contextTag(type, atLocation)),
3695
+ contextTag(type, atLocation),
3655
3696
  option
3656
3697
  );
3657
3698
  if (isSome2(parsedContextTag)) {
@@ -3693,6 +3734,7 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
3693
3734
  (atLocation) => atLocation
3694
3735
  );
3695
3736
  return {
3737
+ isNodeReferenceToEffectModuleApi,
3696
3738
  effectType,
3697
3739
  strictEffectType,
3698
3740
  layerType,
@@ -4075,6 +4117,80 @@ var effectDataClasses = createCompletion({
4075
4117
  })
4076
4118
  });
4077
4119
 
4120
+ // src/diagnostics/catchUnfailableEffect.ts
4121
+ var catchUnfailableEffect = createDiagnostic({
4122
+ name: "catchUnfailableEffect",
4123
+ code: 2,
4124
+ severity: "suggestion",
4125
+ apply: fn("catchUnfailableEffect.apply")(function* (sourceFile, report) {
4126
+ const ts = yield* service(TypeScriptApi);
4127
+ const typeParser = yield* service(TypeParser);
4128
+ const typeChecker = yield* service(TypeCheckerApi);
4129
+ const nodeToVisit = [];
4130
+ const appendNodeToVisit = (node) => {
4131
+ nodeToVisit.push(node);
4132
+ return void 0;
4133
+ };
4134
+ ts.forEachChild(sourceFile, appendNodeToVisit);
4135
+ while (nodeToVisit.length > 0) {
4136
+ const node = nodeToVisit.shift();
4137
+ ts.forEachChild(node, appendNodeToVisit);
4138
+ if (ts.isCallExpression(node)) {
4139
+ const catchFunctions = ["catchAll", "catch", "catchIf", "catchSome", "catchTag", "catchTags"];
4140
+ const isCatchCall = yield* pipe(
4141
+ firstSuccessOf(
4142
+ catchFunctions.map((catchFn) => typeParser.isNodeReferenceToEffectModuleApi(catchFn)(node.expression))
4143
+ ),
4144
+ option
4145
+ );
4146
+ if (isSome2(isCatchCall)) {
4147
+ const parent = node.parent;
4148
+ if (parent && ts.isCallExpression(parent)) {
4149
+ const pipeCallResult = yield* pipe(
4150
+ typeParser.pipeCall(parent),
4151
+ option
4152
+ );
4153
+ if (isSome2(pipeCallResult)) {
4154
+ const { args: args2, node: pipeCallNode, subject } = pipeCallResult.value;
4155
+ const argIndex = args2.findIndex((arg) => arg === node);
4156
+ if (argIndex !== -1) {
4157
+ let effectTypeToCheck;
4158
+ if (argIndex === 0) {
4159
+ effectTypeToCheck = typeChecker.getTypeAtLocation(subject);
4160
+ } else {
4161
+ const signature = typeChecker.getResolvedSignature(pipeCallNode);
4162
+ if (signature) {
4163
+ const typeArguments = typeChecker.getTypeArgumentsForResolvedSignature(signature);
4164
+ if (typeArguments && typeArguments.length > argIndex) {
4165
+ effectTypeToCheck = typeArguments[argIndex];
4166
+ }
4167
+ }
4168
+ }
4169
+ if (effectTypeToCheck) {
4170
+ const effectType = yield* pipe(
4171
+ typeParser.effectType(effectTypeToCheck, node),
4172
+ option
4173
+ );
4174
+ if (isSome2(effectType)) {
4175
+ const { E } = effectType.value;
4176
+ if (E.flags & ts.TypeFlags.Never) {
4177
+ report({
4178
+ location: node.expression,
4179
+ messageText: `Looks like the previous effect never fails, so probably this error handling will never be triggered.`,
4180
+ fixes: []
4181
+ });
4182
+ }
4183
+ }
4184
+ }
4185
+ }
4186
+ }
4187
+ }
4188
+ }
4189
+ }
4190
+ }
4191
+ })
4192
+ });
4193
+
4078
4194
  // node_modules/.pnpm/@pkg.pr.new+Effect-TS+effect@97ff1dc_6ntygjheib5kdugabxjhox4fte/node_modules/effect/dist/esm/Chunk.js
4079
4195
  var TypeId3 = /* @__PURE__ */ Symbol.for("effect/Chunk");
4080
4196
  function copy(src, srcPos, dest, destPos, len) {
@@ -7533,11 +7649,11 @@ var multipleEffectProvide = createDiagnostic({
7533
7649
  "Layer"
7534
7650
  ) || "Layer";
7535
7651
  const parseEffectProvideLayer = (node) => {
7536
- if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.isIdentifier(node.expression.name) && ts.idText(node.expression.name) === "provide" && node.arguments.length > 0) {
7652
+ if (ts.isCallExpression(node) && node.arguments.length > 0) {
7537
7653
  const layer = node.arguments[0];
7538
7654
  const type = typeChecker.getTypeAtLocation(layer);
7539
7655
  return pipe(
7540
- typeParser.importedEffectModule(node.expression.expression),
7656
+ typeParser.isNodeReferenceToEffectModuleApi("provide")(node.expression),
7541
7657
  flatMap2(() => typeParser.layerType(type, layer)),
7542
7658
  map5(() => ({ layer, node })),
7543
7659
  orElse2(() => void_)
@@ -8092,10 +8208,10 @@ var strictEffectProvide = createDiagnostic({
8092
8208
  const typeChecker = yield* service(TypeCheckerApi);
8093
8209
  const typeParser = yield* service(TypeParser);
8094
8210
  const parseEffectProvideWithLayer = (node) => gen(function* () {
8095
- if (!ts.isCallExpression(node) || !ts.isPropertyAccessExpression(node.expression) || !ts.isIdentifier(node.expression.name) || ts.idText(node.expression.name) !== "provide" || node.arguments.length === 0) {
8211
+ if (!ts.isCallExpression(node) || node.arguments.length === 0) {
8096
8212
  return yield* typeParserIssue("Not an Effect.provide call");
8097
8213
  }
8098
- yield* typeParser.importedEffectModule(node.expression.expression);
8214
+ yield* typeParser.isNodeReferenceToEffectModuleApi("provide")(node.expression);
8099
8215
  return yield* firstSuccessOf(
8100
8216
  node.arguments.map((arg) => {
8101
8217
  const argType = typeChecker.getTypeAtLocation(arg);
@@ -8390,6 +8506,7 @@ var unsupportedServiceAccessors = createDiagnostic({
8390
8506
 
8391
8507
  // src/diagnostics.ts
8392
8508
  var diagnostics = [
8509
+ catchUnfailableEffect,
8393
8510
  classSelfMismatch,
8394
8511
  duplicatePackage,
8395
8512
  effectGenUsesAdapter,
@@ -13935,11 +14052,20 @@ var extractLayerGraph = fn("extractLayerGraph")(function* (node, opts) {
13935
14052
  });
13936
14053
  var formatLayerGraph = fn("formatLayerGraph")(function* (layerGraph) {
13937
14054
  const tsUtils = yield* service(TypeScriptUtils);
14055
+ const typeChecker = yield* service(TypeCheckerApi);
14056
+ const ts = yield* service(TypeScriptApi);
13938
14057
  return toMermaid(layerGraph, {
13939
14058
  edgeLabel: (edge) => JSON.stringify(edge),
13940
14059
  nodeLabel: (graphNode) => {
13941
14060
  const sourceFile = tsUtils.getSourceFileOfNode(graphNode.node);
13942
- return sourceFile.text.substring(graphNode.node.pos, graphNode.node.end).trim();
14061
+ let text = sourceFile.text.substring(graphNode.node.pos, graphNode.node.end).trim();
14062
+ text += "\nprovides: " + graphNode.provides.map((_) => typeChecker.typeToString(_, void 0, ts.TypeFormatFlags.NoTruncation)).join(
14063
+ ", "
14064
+ );
14065
+ text += "\nrequires: " + graphNode.requires.map((_) => typeChecker.typeToString(_, void 0, ts.TypeFormatFlags.NoTruncation)).join(
14066
+ ", "
14067
+ );
14068
+ return text;
13943
14069
  }
13944
14070
  });
13945
14071
  });
@@ -14020,7 +14146,7 @@ var formatNestedLayerGraph = fn("formatNestedLayerGraph")(function* (layerGraph)
14020
14146
  var extractOutlineGraph = fn("extractOutlineGraph")(function* (layerGraph) {
14021
14147
  const typeChecker = yield* service(TypeCheckerApi);
14022
14148
  const mutableGraph = beginMutation3(directed());
14023
- const providers = /* @__PURE__ */ new WeakMap();
14149
+ const providers = /* @__PURE__ */ new Map();
14024
14150
  const knownSymbols = /* @__PURE__ */ new WeakSet();
14025
14151
  const leafNodes = values2(externals(layerGraph, { direction: "outgoing" }));
14026
14152
  const dedupedLeafNodes = [];
@@ -14047,8 +14173,12 @@ var extractOutlineGraph = fn("extractOutlineGraph")(function* (layerGraph) {
14047
14173
  }
14048
14174
  for (const [nodeIndex, nodeInfo] of entries(nodes(mutableGraph))) {
14049
14175
  for (const requiredType of nodeInfo.requires) {
14050
- for (const providerNodeIndex of providers.get(requiredType) || []) {
14051
- addEdge(mutableGraph, nodeIndex, providerNodeIndex, {});
14176
+ for (const [providedType, providerNodeIndexes] of providers.entries()) {
14177
+ if (requiredType === providedType || typeChecker.isTypeAssignableTo(requiredType, providedType)) {
14178
+ for (const providerNodeIndex of providerNodeIndexes) {
14179
+ addEdge(mutableGraph, nodeIndex, providerNodeIndex, {});
14180
+ }
14181
+ }
14052
14182
  }
14053
14183
  }
14054
14184
  }
@@ -14135,7 +14265,8 @@ var walkLeavesMatching = (graph, predicate, config = {}) => {
14135
14265
  var extractProvidersAndRequirers = fn("extractProvidersAndRequirers")(
14136
14266
  function* (layerGraph) {
14137
14267
  const typeCheckerUtils = yield* service(TypeCheckerUtils);
14138
- const rootWalker = externals(layerGraph, { direction: "outgoing" });
14268
+ const typeChecker = yield* service(TypeCheckerApi);
14269
+ const rootWalker = externals(layerGraph, { direction: "incoming" });
14139
14270
  const rootNodes = fromIterable(values2(rootWalker));
14140
14271
  const rootNodeIndexes = fromIterable(indices(rootWalker));
14141
14272
  const result = [];
@@ -14146,7 +14277,9 @@ var extractProvidersAndRequirers = fn("extractProvidersAndRequirers")(
14146
14277
  for (const layerNode of values2(
14147
14278
  walkLeavesMatching(
14148
14279
  layerGraph,
14149
- (_) => (kind === "provided" ? _.provides : _.requires).indexOf(layerType) > -1,
14280
+ (_) => (kind === "provided" ? _.provides : _.requires).some(
14281
+ (_2) => _2 === layerType || typeChecker.isTypeAssignableTo(_2, layerType)
14282
+ ),
14150
14283
  { start: rootNodeIndexes }
14151
14284
  )
14152
14285
  )) {