@effect/language-service 0.58.4 → 0.60.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.
@@ -1212,7 +1212,8 @@ var defaults = {
1212
1212
  }],
1213
1213
  extendedKeyDetection: false,
1214
1214
  pipeableMinArgCount: 1,
1215
- layerGraphFollowDepth: 0
1215
+ layerGraphFollowDepth: 0,
1216
+ mermaidProvider: "mermaid.live"
1216
1217
  };
1217
1218
  function parseKeyPatterns(patterns) {
1218
1219
  const result = [];
@@ -1250,7 +1251,8 @@ function parse(config) {
1250
1251
  keyPatterns: isObject(config) && hasProperty(config, "keyPatterns") && isArray(config.keyPatterns) ? parseKeyPatterns(config.keyPatterns) : defaults.keyPatterns,
1251
1252
  extendedKeyDetection: isObject(config) && hasProperty(config, "extendedKeyDetection") && isBoolean(config.extendedKeyDetection) ? config.extendedKeyDetection : defaults.extendedKeyDetection,
1252
1253
  pipeableMinArgCount: isObject(config) && hasProperty(config, "pipeableMinArgCount") && isNumber(config.pipeableMinArgCount) ? config.pipeableMinArgCount : defaults.pipeableMinArgCount,
1253
- layerGraphFollowDepth: isObject(config) && hasProperty(config, "layerGraphFollowDepth") && isNumber(config.layerGraphFollowDepth) ? config.layerGraphFollowDepth : defaults.layerGraphFollowDepth
1254
+ layerGraphFollowDepth: isObject(config) && hasProperty(config, "layerGraphFollowDepth") && isNumber(config.layerGraphFollowDepth) ? config.layerGraphFollowDepth : defaults.layerGraphFollowDepth,
1255
+ mermaidProvider: isObject(config) && hasProperty(config, "mermaidProvider") && isString(config.mermaidProvider) ? config.mermaidProvider : defaults.mermaidProvider
1254
1256
  };
1255
1257
  }
1256
1258
 
@@ -2844,67 +2846,69 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
2844
2846
  "TypeParser.effectSubtype",
2845
2847
  (type) => type
2846
2848
  );
2847
- const importedContextModule = cachedBy(
2848
- fn("TypeParser.importedContextModule")(function* (node) {
2849
- if (!ts.isIdentifier(node)) {
2850
- return yield* typeParserIssue("Node is not an identifier", void 0, node);
2851
- }
2852
- const type = typeChecker.getTypeAtLocation(node);
2853
- const propertySymbol = typeChecker.getPropertyOfType(type, "Tag");
2854
- if (!propertySymbol) {
2855
- return yield* typeParserIssue("Type has no 'Tag' property", type, node);
2856
- }
2857
- const sourceFile = tsUtils.getSourceFileOfNode(node);
2858
- if (!sourceFile) {
2859
- return yield* typeParserIssue("Node is not in a source file", void 0, node);
2860
- }
2861
- const contextIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
2862
- sourceFile,
2863
- "effect",
2864
- "Context"
2865
- );
2866
- if (!contextIdentifier) {
2867
- return yield* typeParserIssue("Context module not found", void 0, node);
2868
- }
2869
- if (ts.idText(node) !== contextIdentifier) {
2870
- return yield* typeParserIssue("Node is not a context module reference", void 0, node);
2871
- }
2872
- return node;
2849
+ const isEffectContextSourceFile = cachedBy(
2850
+ fn("TypeParser.isEffectContextSourceFile")(function* (sourceFile) {
2851
+ const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
2852
+ if (!moduleSymbol) return yield* typeParserIssue("Node has no symbol", void 0, sourceFile);
2853
+ const contextSymbol = typeChecker.tryGetMemberInModuleExports("Context", moduleSymbol);
2854
+ if (!contextSymbol) return yield* typeParserIssue("Context not found", void 0, sourceFile);
2855
+ const tagSymbol = typeChecker.tryGetMemberInModuleExports("Tag", moduleSymbol);
2856
+ if (!tagSymbol) return yield* typeParserIssue("Tag not found", void 0, sourceFile);
2857
+ const tagType = typeChecker.getDeclaredTypeOfSymbol(tagSymbol);
2858
+ yield* contextTag(tagType, sourceFile);
2859
+ return sourceFile;
2860
+ }),
2861
+ "TypeParser.isEffectContextSourceFile",
2862
+ (sourceFile) => sourceFile
2863
+ );
2864
+ const isNodeReferenceToEffectContextModuleApi = (memberName) => cachedBy(
2865
+ fn("TypeParser.isNodeReferenceToEffectContextModuleApi")(function* (node) {
2866
+ return yield* isNodeReferenceToExportOfPackageModule(node, "effect", isEffectContextSourceFile, memberName);
2873
2867
  }),
2868
+ `TypeParser.isNodeReferenceToEffectContextModuleApi(${memberName})`,
2869
+ (node) => node
2870
+ );
2871
+ const importedContextModule = cachedBy(
2872
+ (node) => pipe(
2873
+ isNodeReferenceToPackageModule(node, "effect", isEffectContextSourceFile),
2874
+ map4(() => node)
2875
+ ),
2874
2876
  "TypeParser.importedContextModule",
2875
2877
  (node) => node
2876
2878
  );
2877
- const importedEffectModule = (node) => pipe(
2878
- isNodeReferenceToPackageModule(node, "effect", isEffectTypeSourceFile),
2879
- map4(() => node)
2879
+ const importedEffectModule = cachedBy(
2880
+ (node) => pipe(
2881
+ isNodeReferenceToPackageModule(node, "effect", isEffectTypeSourceFile),
2882
+ map4(() => node)
2883
+ ),
2884
+ "TypeParser.importedEffectModule",
2885
+ (node) => node
2886
+ );
2887
+ const isEffectDataSourceFile = cachedBy(
2888
+ fn("TypeParser.isEffectDataSourceFile")(function* (sourceFile) {
2889
+ const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
2890
+ if (!moduleSymbol) return yield* typeParserIssue("Node has no symbol", void 0, sourceFile);
2891
+ const taggedEnumSymbol = typeChecker.tryGetMemberInModuleExports("TaggedEnum", moduleSymbol);
2892
+ if (!taggedEnumSymbol) return yield* typeParserIssue("TaggedEnum not found", void 0, sourceFile);
2893
+ const taggedErrorSymbol = typeChecker.tryGetMemberInModuleExports("TaggedError", moduleSymbol);
2894
+ if (!taggedErrorSymbol) return yield* typeParserIssue("TaggedError not found", void 0, sourceFile);
2895
+ return sourceFile;
2896
+ }),
2897
+ "TypeParser.isEffectDataSourceFile",
2898
+ (sourceFile) => sourceFile
2880
2899
  );
2881
- const importedDataModule = cachedBy(
2882
- fn("TypeParser.importedDataModule")(function* (node) {
2883
- if (!ts.isIdentifier(node)) {
2884
- return yield* typeParserIssue("Node is not an expression", void 0, node);
2885
- }
2886
- const type = typeChecker.getTypeAtLocation(node);
2887
- const propertySymbol = typeChecker.getPropertyOfType(type, "TaggedError");
2888
- if (!propertySymbol) {
2889
- return yield* typeParserIssue("Type has no 'TaggedError' property", type, node);
2890
- }
2891
- const sourceFile = tsUtils.getSourceFileOfNode(node);
2892
- if (!sourceFile) {
2893
- return yield* typeParserIssue("Node is not in a source file", void 0, node);
2894
- }
2895
- const dataIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
2896
- sourceFile,
2897
- "effect",
2898
- "Data"
2899
- );
2900
- if (!dataIdentifier) {
2901
- return yield* typeParserIssue("Data module not found", void 0, node);
2902
- }
2903
- if (ts.idText(node) !== dataIdentifier) {
2904
- return yield* typeParserIssue("Node is not a data module reference", void 0, node);
2905
- }
2906
- return node;
2900
+ const isNodeReferenceToEffectDataModuleApi = (memberName) => cachedBy(
2901
+ fn("TypeParser.isNodeReferenceToEffectDataModuleApi")(function* (node) {
2902
+ return yield* isNodeReferenceToExportOfPackageModule(node, "effect", isEffectDataSourceFile, memberName);
2907
2903
  }),
2904
+ `TypeParser.isNodeReferenceToEffectDataModuleApi(${memberName})`,
2905
+ (node) => node
2906
+ );
2907
+ const importedDataModule = cachedBy(
2908
+ (node) => pipe(
2909
+ isNodeReferenceToPackageModule(node, "effect", isEffectDataSourceFile),
2910
+ map4(() => node)
2911
+ ),
2908
2912
  "TypeParser.importedDataModule",
2909
2913
  (node) => node
2910
2914
  );
@@ -3643,6 +3647,8 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
3643
3647
  return {
3644
3648
  isNodeReferenceToEffectModuleApi,
3645
3649
  isNodeReferenceToEffectSchemaModuleApi,
3650
+ isNodeReferenceToEffectDataModuleApi,
3651
+ isNodeReferenceToEffectContextModuleApi,
3646
3652
  effectType,
3647
3653
  strictEffectType,
3648
3654
  layerType,
@@ -6046,6 +6052,85 @@ Consider extracting the Runtime by using for example Effect.runtime and then use
6046
6052
  })
6047
6053
  });
6048
6054
 
6055
+ // src/diagnostics/schemaStructWithTag.ts
6056
+ var schemaStructWithTag = createDiagnostic({
6057
+ name: "schemaStructWithTag",
6058
+ code: 34,
6059
+ severity: "suggestion",
6060
+ apply: fn("schemaStructWithTag.apply")(function* (sourceFile, report) {
6061
+ const ts = yield* service(TypeScriptApi);
6062
+ const typeParser = yield* service(TypeParser);
6063
+ const nodeToVisit = [];
6064
+ const appendNodeToVisit = (node) => {
6065
+ nodeToVisit.push(node);
6066
+ return void 0;
6067
+ };
6068
+ ts.forEachChild(sourceFile, appendNodeToVisit);
6069
+ while (nodeToVisit.length > 0) {
6070
+ const node = nodeToVisit.shift();
6071
+ if (ts.isCallExpression(node)) {
6072
+ const isSchemaStructCall = yield* pipe(
6073
+ typeParser.isNodeReferenceToEffectSchemaModuleApi("Struct")(node.expression),
6074
+ orElse2(() => void_)
6075
+ );
6076
+ if (isSchemaStructCall && node.arguments.length === 1) {
6077
+ const arg = node.arguments[0];
6078
+ if (ts.isObjectLiteralExpression(arg)) {
6079
+ const tagProperty = arg.properties.find(
6080
+ (prop) => ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && ts.idText(prop.name) === "_tag"
6081
+ );
6082
+ if (tagProperty && ts.isCallExpression(tagProperty.initializer)) {
6083
+ const isSchemaLiteralCall = yield* pipe(
6084
+ typeParser.isNodeReferenceToEffectSchemaModuleApi("Literal")(
6085
+ tagProperty.initializer.expression
6086
+ ),
6087
+ option
6088
+ );
6089
+ if (isSchemaLiteralCall._tag === "Some") {
6090
+ const literalCall = tagProperty.initializer;
6091
+ const literalArgs = fromIterable(literalCall.arguments);
6092
+ if (literalArgs.length === 1 && ts.isStringLiteral(literalArgs[0])) {
6093
+ const tagValue = literalArgs[0].text;
6094
+ const otherProperties = arg.properties.filter((prop) => prop !== tagProperty);
6095
+ report({
6096
+ location: node,
6097
+ messageText: "Schema.Struct with a _tag field can be simplified to Schema.TaggedStruct to make the tag optional in the constructor.",
6098
+ fixes: [{
6099
+ fixName: "schemaStructWithTag_fix",
6100
+ description: "Replace with Schema.TaggedStruct",
6101
+ apply: gen(function* () {
6102
+ const changeTracker = yield* service(ChangeTracker);
6103
+ const newObjectLiteral = ts.factory.createObjectLiteralExpression(
6104
+ otherProperties,
6105
+ true
6106
+ );
6107
+ const newNode = ts.factory.createCallExpression(
6108
+ ts.factory.createPropertyAccessExpression(
6109
+ // Reuse the Schema identifier from the original expression
6110
+ ts.isPropertyAccessExpression(node.expression) ? node.expression.expression : ts.factory.createIdentifier("Schema"),
6111
+ "TaggedStruct"
6112
+ ),
6113
+ void 0,
6114
+ [
6115
+ ts.factory.createStringLiteral(tagValue),
6116
+ newObjectLiteral
6117
+ ]
6118
+ );
6119
+ changeTracker.replaceNode(sourceFile, node, newNode);
6120
+ })
6121
+ }]
6122
+ });
6123
+ }
6124
+ }
6125
+ }
6126
+ }
6127
+ }
6128
+ }
6129
+ ts.forEachChild(node, appendNodeToVisit);
6130
+ }
6131
+ })
6132
+ });
6133
+
6049
6134
  // src/diagnostics/schemaUnionOfLiterals.ts
6050
6135
  var schemaUnionOfLiterals = createDiagnostic({
6051
6136
  name: "schemaUnionOfLiterals",
@@ -6737,7 +6822,8 @@ var diagnostics = [
6737
6822
  strictEffectProvide,
6738
6823
  unknownInEffectCatch,
6739
6824
  runEffectInsideEffect,
6740
- schemaUnionOfLiterals
6825
+ schemaUnionOfLiterals,
6826
+ schemaStructWithTag
6741
6827
  ];
6742
6828
 
6743
6829
  // src/effect-lsp-patch-utils.ts