@effect/language-service 0.58.3 → 0.59.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.
@@ -2580,7 +2580,16 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
2580
2580
  const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
2581
2581
  if (!moduleSymbol) continue;
2582
2582
  const memberSymbol = typeChecker.tryGetMemberInModuleExports(memberName, moduleSymbol);
2583
- if (memberSymbol && memberSymbol === symbol3) result.push({ memberSymbol, moduleSymbol, sourceFile });
2583
+ if (memberSymbol) {
2584
+ if (memberSymbol === symbol3) {
2585
+ result.push({ memberSymbol, moduleSymbol, sourceFile });
2586
+ } else if (memberSymbol.flags & ts.SymbolFlags.Alias) {
2587
+ const aliased = typeChecker.getAliasedSymbol(memberSymbol);
2588
+ if (aliased === symbol3) {
2589
+ result.push({ memberSymbol, moduleSymbol, sourceFile });
2590
+ }
2591
+ }
2592
+ }
2584
2593
  }
2585
2594
  if (result.length > 0) {
2586
2595
  return result;
@@ -2835,67 +2844,69 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
2835
2844
  "TypeParser.effectSubtype",
2836
2845
  (type) => type
2837
2846
  );
2838
- const importedContextModule = cachedBy(
2839
- fn("TypeParser.importedContextModule")(function* (node) {
2840
- if (!ts.isIdentifier(node)) {
2841
- return yield* typeParserIssue("Node is not an identifier", void 0, node);
2842
- }
2843
- const type = typeChecker.getTypeAtLocation(node);
2844
- const propertySymbol = typeChecker.getPropertyOfType(type, "Tag");
2845
- if (!propertySymbol) {
2846
- return yield* typeParserIssue("Type has no 'Tag' property", type, node);
2847
- }
2848
- const sourceFile = tsUtils.getSourceFileOfNode(node);
2849
- if (!sourceFile) {
2850
- return yield* typeParserIssue("Node is not in a source file", void 0, node);
2851
- }
2852
- const contextIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
2853
- sourceFile,
2854
- "effect",
2855
- "Context"
2856
- );
2857
- if (!contextIdentifier) {
2858
- return yield* typeParserIssue("Context module not found", void 0, node);
2859
- }
2860
- if (ts.idText(node) !== contextIdentifier) {
2861
- return yield* typeParserIssue("Node is not a context module reference", void 0, node);
2862
- }
2863
- return node;
2847
+ const isEffectContextSourceFile = cachedBy(
2848
+ fn("TypeParser.isEffectContextSourceFile")(function* (sourceFile) {
2849
+ const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
2850
+ if (!moduleSymbol) return yield* typeParserIssue("Node has no symbol", void 0, sourceFile);
2851
+ const contextSymbol = typeChecker.tryGetMemberInModuleExports("Context", moduleSymbol);
2852
+ if (!contextSymbol) return yield* typeParserIssue("Context not found", void 0, sourceFile);
2853
+ const tagSymbol = typeChecker.tryGetMemberInModuleExports("Tag", moduleSymbol);
2854
+ if (!tagSymbol) return yield* typeParserIssue("Tag not found", void 0, sourceFile);
2855
+ const tagType = typeChecker.getDeclaredTypeOfSymbol(tagSymbol);
2856
+ yield* contextTag(tagType, sourceFile);
2857
+ return sourceFile;
2858
+ }),
2859
+ "TypeParser.isEffectContextSourceFile",
2860
+ (sourceFile) => sourceFile
2861
+ );
2862
+ const isNodeReferenceToEffectContextModuleApi = (memberName) => cachedBy(
2863
+ fn("TypeParser.isNodeReferenceToEffectContextModuleApi")(function* (node) {
2864
+ return yield* isNodeReferenceToExportOfPackageModule(node, "effect", isEffectContextSourceFile, memberName);
2864
2865
  }),
2866
+ `TypeParser.isNodeReferenceToEffectContextModuleApi(${memberName})`,
2867
+ (node) => node
2868
+ );
2869
+ const importedContextModule = cachedBy(
2870
+ (node) => pipe(
2871
+ isNodeReferenceToPackageModule(node, "effect", isEffectContextSourceFile),
2872
+ map4(() => node)
2873
+ ),
2865
2874
  "TypeParser.importedContextModule",
2866
2875
  (node) => node
2867
2876
  );
2868
- const importedEffectModule = (node) => pipe(
2869
- isNodeReferenceToPackageModule(node, "effect", isEffectTypeSourceFile),
2870
- map4(() => node)
2877
+ const importedEffectModule = cachedBy(
2878
+ (node) => pipe(
2879
+ isNodeReferenceToPackageModule(node, "effect", isEffectTypeSourceFile),
2880
+ map4(() => node)
2881
+ ),
2882
+ "TypeParser.importedEffectModule",
2883
+ (node) => node
2871
2884
  );
2872
- const importedDataModule = cachedBy(
2873
- fn("TypeParser.importedDataModule")(function* (node) {
2874
- if (!ts.isIdentifier(node)) {
2875
- return yield* typeParserIssue("Node is not an expression", void 0, node);
2876
- }
2877
- const type = typeChecker.getTypeAtLocation(node);
2878
- const propertySymbol = typeChecker.getPropertyOfType(type, "TaggedError");
2879
- if (!propertySymbol) {
2880
- return yield* typeParserIssue("Type has no 'TaggedError' property", type, node);
2881
- }
2882
- const sourceFile = tsUtils.getSourceFileOfNode(node);
2883
- if (!sourceFile) {
2884
- return yield* typeParserIssue("Node is not in a source file", void 0, node);
2885
- }
2886
- const dataIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
2887
- sourceFile,
2888
- "effect",
2889
- "Data"
2890
- );
2891
- if (!dataIdentifier) {
2892
- return yield* typeParserIssue("Data module not found", void 0, node);
2893
- }
2894
- if (ts.idText(node) !== dataIdentifier) {
2895
- return yield* typeParserIssue("Node is not a data module reference", void 0, node);
2896
- }
2897
- return node;
2885
+ const isEffectDataSourceFile = cachedBy(
2886
+ fn("TypeParser.isEffectDataSourceFile")(function* (sourceFile) {
2887
+ const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
2888
+ if (!moduleSymbol) return yield* typeParserIssue("Node has no symbol", void 0, sourceFile);
2889
+ const taggedEnumSymbol = typeChecker.tryGetMemberInModuleExports("TaggedEnum", moduleSymbol);
2890
+ if (!taggedEnumSymbol) return yield* typeParserIssue("TaggedEnum not found", void 0, sourceFile);
2891
+ const taggedErrorSymbol = typeChecker.tryGetMemberInModuleExports("TaggedError", moduleSymbol);
2892
+ if (!taggedErrorSymbol) return yield* typeParserIssue("TaggedError not found", void 0, sourceFile);
2893
+ return sourceFile;
2898
2894
  }),
2895
+ "TypeParser.isEffectDataSourceFile",
2896
+ (sourceFile) => sourceFile
2897
+ );
2898
+ const isNodeReferenceToEffectDataModuleApi = (memberName) => cachedBy(
2899
+ fn("TypeParser.isNodeReferenceToEffectDataModuleApi")(function* (node) {
2900
+ return yield* isNodeReferenceToExportOfPackageModule(node, "effect", isEffectDataSourceFile, memberName);
2901
+ }),
2902
+ `TypeParser.isNodeReferenceToEffectDataModuleApi(${memberName})`,
2903
+ (node) => node
2904
+ );
2905
+ const importedDataModule = cachedBy(
2906
+ (node) => pipe(
2907
+ isNodeReferenceToPackageModule(node, "effect", isEffectDataSourceFile),
2908
+ map4(() => node)
2909
+ ),
2899
2910
  "TypeParser.importedDataModule",
2900
2911
  (node) => node
2901
2912
  );
@@ -3634,6 +3645,8 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
3634
3645
  return {
3635
3646
  isNodeReferenceToEffectModuleApi,
3636
3647
  isNodeReferenceToEffectSchemaModuleApi,
3648
+ isNodeReferenceToEffectDataModuleApi,
3649
+ isNodeReferenceToEffectContextModuleApi,
3637
3650
  effectType,
3638
3651
  strictEffectType,
3639
3652
  layerType,
@@ -5597,7 +5610,7 @@ var annotate = createCodegen({
5597
5610
  const initializerTypeNode = fromNullable(typeCheckerUtils.typeToSimplifiedTypeNode(
5598
5611
  initializerType,
5599
5612
  enclosingNode,
5600
- ts.NodeBuilderFlags.NoTruncation
5613
+ ts.NodeBuilderFlags.NoTruncation | ts.NodeBuilderFlags.IgnoreErrors
5601
5614
  )).pipe(
5602
5615
  getOrUndefined
5603
5616
  );
@@ -6037,6 +6050,85 @@ Consider extracting the Runtime by using for example Effect.runtime and then use
6037
6050
  })
6038
6051
  });
6039
6052
 
6053
+ // src/diagnostics/schemaStructWithTag.ts
6054
+ var schemaStructWithTag = createDiagnostic({
6055
+ name: "schemaStructWithTag",
6056
+ code: 34,
6057
+ severity: "suggestion",
6058
+ apply: fn("schemaStructWithTag.apply")(function* (sourceFile, report) {
6059
+ const ts = yield* service(TypeScriptApi);
6060
+ const typeParser = yield* service(TypeParser);
6061
+ const nodeToVisit = [];
6062
+ const appendNodeToVisit = (node) => {
6063
+ nodeToVisit.push(node);
6064
+ return void 0;
6065
+ };
6066
+ ts.forEachChild(sourceFile, appendNodeToVisit);
6067
+ while (nodeToVisit.length > 0) {
6068
+ const node = nodeToVisit.shift();
6069
+ if (ts.isCallExpression(node)) {
6070
+ const isSchemaStructCall = yield* pipe(
6071
+ typeParser.isNodeReferenceToEffectSchemaModuleApi("Struct")(node.expression),
6072
+ orElse2(() => void_)
6073
+ );
6074
+ if (isSchemaStructCall && node.arguments.length === 1) {
6075
+ const arg = node.arguments[0];
6076
+ if (ts.isObjectLiteralExpression(arg)) {
6077
+ const tagProperty = arg.properties.find(
6078
+ (prop) => ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && ts.idText(prop.name) === "_tag"
6079
+ );
6080
+ if (tagProperty && ts.isCallExpression(tagProperty.initializer)) {
6081
+ const isSchemaLiteralCall = yield* pipe(
6082
+ typeParser.isNodeReferenceToEffectSchemaModuleApi("Literal")(
6083
+ tagProperty.initializer.expression
6084
+ ),
6085
+ option
6086
+ );
6087
+ if (isSchemaLiteralCall._tag === "Some") {
6088
+ const literalCall = tagProperty.initializer;
6089
+ const literalArgs = fromIterable(literalCall.arguments);
6090
+ if (literalArgs.length === 1 && ts.isStringLiteral(literalArgs[0])) {
6091
+ const tagValue = literalArgs[0].text;
6092
+ const otherProperties = arg.properties.filter((prop) => prop !== tagProperty);
6093
+ report({
6094
+ location: node,
6095
+ messageText: "Schema.Struct with a _tag field can be simplified to Schema.TaggedStruct to make the tag optional in the constructor.",
6096
+ fixes: [{
6097
+ fixName: "schemaStructWithTag_fix",
6098
+ description: "Replace with Schema.TaggedStruct",
6099
+ apply: gen(function* () {
6100
+ const changeTracker = yield* service(ChangeTracker);
6101
+ const newObjectLiteral = ts.factory.createObjectLiteralExpression(
6102
+ otherProperties,
6103
+ true
6104
+ );
6105
+ const newNode = ts.factory.createCallExpression(
6106
+ ts.factory.createPropertyAccessExpression(
6107
+ // Reuse the Schema identifier from the original expression
6108
+ ts.isPropertyAccessExpression(node.expression) ? node.expression.expression : ts.factory.createIdentifier("Schema"),
6109
+ "TaggedStruct"
6110
+ ),
6111
+ void 0,
6112
+ [
6113
+ ts.factory.createStringLiteral(tagValue),
6114
+ newObjectLiteral
6115
+ ]
6116
+ );
6117
+ changeTracker.replaceNode(sourceFile, node, newNode);
6118
+ })
6119
+ }]
6120
+ });
6121
+ }
6122
+ }
6123
+ }
6124
+ }
6125
+ }
6126
+ }
6127
+ ts.forEachChild(node, appendNodeToVisit);
6128
+ }
6129
+ })
6130
+ });
6131
+
6040
6132
  // src/diagnostics/schemaUnionOfLiterals.ts
6041
6133
  var schemaUnionOfLiterals = createDiagnostic({
6042
6134
  name: "schemaUnionOfLiterals",
@@ -6728,7 +6820,8 @@ var diagnostics = [
6728
6820
  strictEffectProvide,
6729
6821
  unknownInEffectCatch,
6730
6822
  runEffectInsideEffect,
6731
- schemaUnionOfLiterals
6823
+ schemaUnionOfLiterals,
6824
+ schemaStructWithTag
6732
6825
  ];
6733
6826
 
6734
6827
  // src/effect-lsp-patch-utils.ts