@effect/language-service 0.39.0 → 0.40.1

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
@@ -1701,7 +1701,8 @@ var defaults = {
1701
1701
  topLevelNamedReexports: "ignore",
1702
1702
  barrelImportPackages: [],
1703
1703
  importAliases: {},
1704
- renames: true
1704
+ renames: true,
1705
+ noExternal: false
1705
1706
  };
1706
1707
  function parse(config) {
1707
1708
  return {
@@ -1718,7 +1719,8 @@ function parse(config) {
1718
1719
  barrelImportPackages: isObject(config) && hasProperty(config, "barrelImportPackages") && isArray(config.barrelImportPackages) && config.barrelImportPackages.every(isString) ? config.barrelImportPackages.map((_) => _.toLowerCase()) : defaults.barrelImportPackages,
1719
1720
  importAliases: isObject(config) && hasProperty(config, "importAliases") && isRecord(config.importAliases) ? map4(config.importAliases, (value) => String(value)) : defaults.importAliases,
1720
1721
  topLevelNamedReexports: isObject(config) && hasProperty(config, "topLevelNamedReexports") && isString(config.topLevelNamedReexports) && ["ignore", "follow"].includes(config.topLevelNamedReexports.toLowerCase()) ? config.topLevelNamedReexports.toLowerCase() : defaults.topLevelNamedReexports,
1721
- renames: isObject(config) && hasProperty(config, "renames") && isBoolean(config.renames) ? config.renames : defaults.renames
1722
+ renames: isObject(config) && hasProperty(config, "renames") && isBoolean(config.renames) ? config.renames : defaults.renames,
1723
+ noExternal: isObject(config) && hasProperty(config, "noExternal") && isBoolean(config.noExternal) ? config.noExternal : defaults.noExternal
1722
1724
  };
1723
1725
  }
1724
1726
 
@@ -2561,13 +2563,28 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
2561
2563
  );
2562
2564
  const importedSchemaModule = cachedBy(
2563
2565
  fn("TypeParser.importedSchemaModule")(function* (node) {
2566
+ if (!ts.isIdentifier(node)) {
2567
+ return yield* typeParserIssue("Node is not an expression", void 0, node);
2568
+ }
2564
2569
  const type = typeChecker.getTypeAtLocation(node);
2565
2570
  const propertySymbol = typeChecker.getPropertyOfType(type, "Class");
2566
2571
  if (!propertySymbol) {
2567
2572
  return yield* typeParserIssue("Type has no 'Class' property", type, node);
2568
2573
  }
2569
- if (!ts.isExpression(node)) {
2570
- return yield* typeParserIssue("Node is not an expression", type, node);
2574
+ const sourceFile = tsUtils.getSourceFileOfNode(node);
2575
+ if (!sourceFile) {
2576
+ return yield* typeParserIssue("Node is not in a source file", void 0, node);
2577
+ }
2578
+ const schemaIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
2579
+ sourceFile,
2580
+ "effect",
2581
+ "Schema"
2582
+ );
2583
+ if (!schemaIdentifier) {
2584
+ return yield* typeParserIssue("Schema module not found", void 0, node);
2585
+ }
2586
+ if (ts.idText(node) !== schemaIdentifier) {
2587
+ return yield* typeParserIssue("Node is not a schema module reference", void 0, node);
2571
2588
  }
2572
2589
  return node;
2573
2590
  }),
@@ -2581,8 +2598,23 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
2581
2598
  if (!propertySymbol) {
2582
2599
  return yield* typeParserIssue("Type has no 'Tag' property", type, node);
2583
2600
  }
2584
- if (!ts.isExpression(node)) {
2585
- return yield* typeParserIssue("Node is not an expression", type, node);
2601
+ if (!ts.isIdentifier(node)) {
2602
+ return yield* typeParserIssue("Node is not an identifier", type, node);
2603
+ }
2604
+ const sourceFile = tsUtils.getSourceFileOfNode(node);
2605
+ if (!sourceFile) {
2606
+ return yield* typeParserIssue("Node is not in a source file", void 0, node);
2607
+ }
2608
+ const contextIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
2609
+ sourceFile,
2610
+ "effect",
2611
+ "Context"
2612
+ );
2613
+ if (!contextIdentifier) {
2614
+ return yield* typeParserIssue("Context module not found", void 0, node);
2615
+ }
2616
+ if (ts.idText(node) !== contextIdentifier) {
2617
+ return yield* typeParserIssue("Node is not a context module reference", void 0, node);
2586
2618
  }
2587
2619
  return node;
2588
2620
  }),
@@ -2613,9 +2645,24 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
2613
2645
  if (!propertySymbol) {
2614
2646
  return yield* typeParserIssue("Type has no 'TaggedError' property", type, node);
2615
2647
  }
2616
- if (!ts.isExpression(node)) {
2648
+ if (!ts.isIdentifier(node)) {
2617
2649
  return yield* typeParserIssue("Node is not an expression", type, node);
2618
2650
  }
2651
+ const sourceFile = tsUtils.getSourceFileOfNode(node);
2652
+ if (!sourceFile) {
2653
+ return yield* typeParserIssue("Node is not in a source file", void 0, node);
2654
+ }
2655
+ const dataIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
2656
+ sourceFile,
2657
+ "effect",
2658
+ "Data"
2659
+ );
2660
+ if (!dataIdentifier) {
2661
+ return yield* typeParserIssue("Data module not found", void 0, node);
2662
+ }
2663
+ if (ts.idText(node) !== dataIdentifier) {
2664
+ return yield* typeParserIssue("Node is not a data module reference", void 0, node);
2665
+ }
2619
2666
  return node;
2620
2667
  }),
2621
2668
  "TypeParser.importedDataModule",
@@ -2978,8 +3025,10 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
2978
3025
  const selfTypeNode = schemaCall.typeArguments[0];
2979
3026
  const schemaIdentifier = schemaCall.expression;
2980
3027
  if (ts.isPropertyAccessExpression(schemaIdentifier) && ts.isIdentifier(schemaIdentifier.name) && ts.idText(schemaIdentifier.name) === "Class") {
3028
+ const expressionType = typeChecker.getTypeAtLocation(expression);
2981
3029
  const parsedSchemaModule = yield* pipe(
2982
- importedSchemaModule(schemaIdentifier.expression),
3030
+ effectSchemaType(expressionType, expression),
3031
+ flatMap(() => importedSchemaModule(schemaIdentifier.expression)),
2983
3032
  option
2984
3033
  );
2985
3034
  if (isSome2(parsedSchemaModule)) {
@@ -3019,8 +3068,10 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
3019
3068
  const selfTypeNode = schemaTaggedClassTCall.typeArguments[0];
3020
3069
  const schemaIdentifier = schemaTaggedClassTCall.expression;
3021
3070
  if (ts.isPropertyAccessExpression(schemaIdentifier) && ts.isIdentifier(schemaIdentifier.name) && ts.idText(schemaIdentifier.name) === "TaggedClass") {
3071
+ const expressionType = typeChecker.getTypeAtLocation(expression);
3022
3072
  const parsedSchemaModule = yield* pipe(
3023
- importedSchemaModule(schemaIdentifier.expression),
3073
+ effectSchemaType(expressionType, expression),
3074
+ flatMap(() => importedSchemaModule(schemaIdentifier.expression)),
3024
3075
  option
3025
3076
  );
3026
3077
  if (isSome2(parsedSchemaModule)) {
@@ -3062,8 +3113,10 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
3062
3113
  const selfTypeNode = schemaTaggedErrorTCall.typeArguments[0];
3063
3114
  const schemaIdentifier = schemaTaggedErrorTCall.expression;
3064
3115
  if (ts.isPropertyAccessExpression(schemaIdentifier) && ts.isIdentifier(schemaIdentifier.name) && ts.idText(schemaIdentifier.name) === "TaggedError") {
3116
+ const expressionType = typeChecker.getTypeAtLocation(expression);
3065
3117
  const parsedSchemaModule = yield* pipe(
3066
- importedSchemaModule(schemaIdentifier.expression),
3118
+ effectSchemaType(expressionType, expression),
3119
+ flatMap(() => importedSchemaModule(schemaIdentifier.expression)),
3067
3120
  option
3068
3121
  );
3069
3122
  if (isSome2(parsedSchemaModule)) {
@@ -3181,8 +3234,10 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
3181
3234
  const selfTypeNode = schemaTaggedRequestTCall.typeArguments[0];
3182
3235
  const schemaIdentifier = schemaTaggedRequestTCall.expression;
3183
3236
  if (ts.isPropertyAccessExpression(schemaIdentifier) && ts.isIdentifier(schemaIdentifier.name) && ts.idText(schemaIdentifier.name) === "TaggedRequest") {
3237
+ const expressionType = typeChecker.getTypeAtLocation(expression);
3184
3238
  const parsedSchemaModule = yield* pipe(
3185
- importedSchemaModule(schemaIdentifier.expression),
3239
+ effectSchemaType(expressionType, expression),
3240
+ flatMap(() => importedSchemaModule(schemaIdentifier.expression)),
3186
3241
  option
3187
3242
  );
3188
3243
  if (isSome2(parsedSchemaModule)) {
@@ -3444,7 +3499,10 @@ var generate = fn("writeTagClassAccessors.generate")(function* (sourceFile, serv
3444
3499
  ]
3445
3500
  );
3446
3501
  return ts.factory.createPropertyDeclaration(
3447
- [ts.factory.createModifier(ts.SyntaxKind.StaticKeyword)],
3502
+ [
3503
+ ts.factory.createModifier(ts.SyntaxKind.StaticKeyword),
3504
+ ts.factory.createModifier(ts.SyntaxKind.OverrideKeyword)
3505
+ ],
3448
3506
  propertyName,
3449
3507
  void 0,
3450
3508
  type,
@@ -3801,6 +3859,7 @@ var classSelfMismatch = createDiagnostic({
3801
3859
  const result = yield* pipe(
3802
3860
  typeParser.extendsEffectService(node),
3803
3861
  orElse2(() => typeParser.extendsContextTag(node)),
3862
+ orElse2(() => typeParser.extendsEffectTag(node)),
3804
3863
  orElse2(() => typeParser.extendsSchemaClass(node)),
3805
3864
  orElse2(() => typeParser.extendsSchemaTaggedClass(node)),
3806
3865
  orElse2(() => typeParser.extendsSchemaTaggedError(node)),
@@ -3809,7 +3868,7 @@ var classSelfMismatch = createDiagnostic({
3809
3868
  );
3810
3869
  if (result) {
3811
3870
  const { className, selfTypeNode } = result;
3812
- let actualName = "";
3871
+ let actualName = sourceFile.text.substring(selfTypeNode.pos, selfTypeNode.end);
3813
3872
  if (ts.isTypeReferenceNode(selfTypeNode)) {
3814
3873
  if (ts.isIdentifier(selfTypeNode.typeName)) {
3815
3874
  actualName = ts.idText(selfTypeNode.typeName);
@@ -3893,6 +3952,43 @@ ${versions.map((version) => `- found ${version} at ${resolvedPackages[packageNam
3893
3952
  })
3894
3953
  });
3895
3954
 
3955
+ // src/diagnostics/effectGenUsesAdapter.ts
3956
+ var effectGenUsesAdapter = createDiagnostic({
3957
+ name: "effectGenUsesAdapter",
3958
+ code: 23,
3959
+ severity: "warning",
3960
+ apply: fn("effectGenUsesAdapter.apply")(function* (sourceFile, report) {
3961
+ const ts = yield* service(TypeScriptApi);
3962
+ const typeParser = yield* service(TypeParser);
3963
+ const nodeToVisit = [];
3964
+ const appendNodeToVisit = (node) => {
3965
+ nodeToVisit.push(node);
3966
+ return void 0;
3967
+ };
3968
+ ts.forEachChild(sourceFile, appendNodeToVisit);
3969
+ while (nodeToVisit.length > 0) {
3970
+ const node = nodeToVisit.shift();
3971
+ ts.forEachChild(node, appendNodeToVisit);
3972
+ if (ts.isCallExpression(node)) {
3973
+ yield* pipe(
3974
+ typeParser.effectGen(node),
3975
+ map3(({ generatorFunction }) => {
3976
+ if (generatorFunction.parameters.length > 0) {
3977
+ const adapter = generatorFunction.parameters[0];
3978
+ report({
3979
+ location: adapter,
3980
+ messageText: `The adapter of Effect.gen is not required anymore, it is now just an alias of pipe.`,
3981
+ fixes: []
3982
+ });
3983
+ }
3984
+ }),
3985
+ ignore
3986
+ );
3987
+ }
3988
+ }
3989
+ })
3990
+ });
3991
+
3896
3992
  // src/diagnostics/effectInVoidSuccess.ts
3897
3993
  var effectInVoidSuccess = createDiagnostic({
3898
3994
  name: "effectInVoidSuccess",
@@ -5410,6 +5506,7 @@ var unsupportedServiceAccessors = createDiagnostic({
5410
5506
  var diagnostics = [
5411
5507
  classSelfMismatch,
5412
5508
  duplicatePackage,
5509
+ effectGenUsesAdapter,
5413
5510
  missingEffectContext,
5414
5511
  missingEffectError,
5415
5512
  missingEffectServiceDependency,
@@ -10996,13 +11093,8 @@ function processNodeMermaid(graph, ctx, ctxL) {
10996
11093
  }
10997
11094
  });
10998
11095
  }
10999
- function generateMarmaidUri(graph, ctxL) {
11096
+ function generateMarmaidUri(code) {
11000
11097
  return gen(function* () {
11001
- const ctx = {
11002
- seenIds: /* @__PURE__ */ new Set()
11003
- };
11004
- const lines = yield* processNodeMermaid(graph, ctx, ctxL);
11005
- const code = "flowchart TB\n" + lines.join("\n");
11006
11098
  const state = JSON.stringify({ code });
11007
11099
  const data = new TextEncoder().encode(state);
11008
11100
  const compressed = deflate_1(data, { level: 9 });
@@ -11010,75 +11102,110 @@ function generateMarmaidUri(graph, ctxL) {
11010
11102
  return "https://www.mermaidchart.com/play#" + pakoString;
11011
11103
  });
11012
11104
  }
11105
+ function getAdjustedNode(sourceFile, position) {
11106
+ return gen(function* () {
11107
+ const ts = yield* service(TypeScriptApi);
11108
+ const tsUtils = yield* service(TypeScriptUtils);
11109
+ const typeChecker = yield* service(TypeCheckerApi);
11110
+ const typeParser = yield* service(TypeParser);
11111
+ const range = tsUtils.toTextRange(position);
11112
+ const maybeNode = pipe(
11113
+ tsUtils.getAncestorNodesInRange(sourceFile, range),
11114
+ filter((_) => ts.isVariableDeclaration(_) || ts.isPropertyDeclaration(_)),
11115
+ filter((_) => tsUtils.isNodeInRange(range)(_.name)),
11116
+ head
11117
+ );
11118
+ if (isNone2(maybeNode)) return void 0;
11119
+ const node = maybeNode.value;
11120
+ const layerNode = node.initializer ? node.initializer : node;
11121
+ const layerType = typeChecker.getTypeAtLocation(layerNode);
11122
+ const maybeLayer = yield* option(typeParser.layerType(layerType, layerNode));
11123
+ if (isNone2(maybeLayer)) return void 0;
11124
+ return { node, layerNode };
11125
+ });
11126
+ }
11127
+ function parseLayerGraph(sourceFile, layerNode) {
11128
+ return gen(function* () {
11129
+ const ts = yield* service(TypeScriptApi);
11130
+ const typeChecker = yield* service(TypeCheckerApi);
11131
+ let lastId = 0;
11132
+ const graphCtx = {
11133
+ services: /* @__PURE__ */ new Map(),
11134
+ serviceTypeToString: /* @__PURE__ */ new Map(),
11135
+ nextId: () => "id" + lastId++
11136
+ };
11137
+ const rootNode = yield* processLayerGraphNode(graphCtx, layerNode, void 0);
11138
+ const ctx = {
11139
+ seenIds: /* @__PURE__ */ new Set()
11140
+ };
11141
+ const mermaidLines = yield* processNodeMermaid(rootNode, ctx, graphCtx);
11142
+ const mermaidCode = "flowchart TB\n" + mermaidLines.join("\n");
11143
+ const textualExplanation = [];
11144
+ const appendInfo = (providesNode, type, kindText) => {
11145
+ const typeString = typeChecker.typeToString(
11146
+ type,
11147
+ void 0,
11148
+ ts.TypeFormatFlags.NoTruncation
11149
+ );
11150
+ const positions = providesNode.map((_) => {
11151
+ const nodePosition = _.node.getStart(sourceFile, false);
11152
+ const { character, line } = ts.getLineAndCharacterOfPosition(sourceFile, nodePosition);
11153
+ const nodeText = _.node.getText().trim().replace(/\n/g, " ").substr(0, 50);
11154
+ return "ln " + (line + 1) + " col " + character + " by `" + nodeText + "`";
11155
+ });
11156
+ textualExplanation.push("- " + typeString + " " + kindText + " at " + positions.join(", "));
11157
+ };
11158
+ for (const providesKey of rootNode.rout) {
11159
+ const providesNode = findInnermostGraphEdge(rootNode, "rout", providesKey);
11160
+ appendInfo(providesNode, graphCtx.services.get(providesKey), "provided");
11161
+ }
11162
+ if (textualExplanation.length > 0) textualExplanation.push("");
11163
+ for (const requiresKey of rootNode.rin) {
11164
+ const requiresNode = findInnermostGraphEdge(rootNode, "rin", requiresKey);
11165
+ appendInfo(requiresNode, graphCtx.services.get(requiresKey), "required");
11166
+ }
11167
+ return { mermaidCode, textualExplanation };
11168
+ });
11169
+ }
11170
+ function effectApiGetLayerGraph(sourceFile, line, character) {
11171
+ return pipe(
11172
+ gen(function* () {
11173
+ const ts = yield* service(TypeScriptApi);
11174
+ const position = ts.getPositionOfLineAndCharacter(sourceFile, line, character);
11175
+ const maybeNodes = yield* getAdjustedNode(sourceFile, position);
11176
+ if (!maybeNodes) return yield* fail(new UnableToProduceLayerGraphError("No node found"));
11177
+ const { layerNode, node } = maybeNodes;
11178
+ const { mermaidCode } = yield* parseLayerGraph(sourceFile, layerNode);
11179
+ return { start: node.pos, end: node.end, mermaidCode };
11180
+ })
11181
+ );
11182
+ }
11013
11183
  function layerInfo(sourceFile, position, quickInfo2) {
11014
11184
  return pipe(
11015
11185
  gen(function* () {
11016
11186
  const ts = yield* service(TypeScriptApi);
11017
- const tsUtils = yield* service(TypeScriptUtils);
11018
- const typeChecker = yield* service(TypeCheckerApi);
11019
- const typeParser = yield* service(TypeParser);
11020
- const range = tsUtils.toTextRange(position);
11021
- const maybeNode = pipe(
11022
- tsUtils.getAncestorNodesInRange(sourceFile, range),
11023
- filter((_) => ts.isVariableDeclaration(_) || ts.isPropertyDeclaration(_)),
11024
- filter((_) => tsUtils.isNodeInRange(range)(_.name)),
11025
- head
11026
- );
11027
- if (isNone2(maybeNode)) return quickInfo2;
11028
- const node = maybeNode.value;
11029
- const layerNode = node.initializer ? node.initializer : node;
11030
- const layerType = typeChecker.getTypeAtLocation(layerNode);
11031
- const maybeLayer = yield* option(typeParser.layerType(layerType, layerNode));
11032
- if (isNone2(maybeLayer)) return quickInfo2;
11033
- let lastId = 0;
11034
- const graphCtx = {
11035
- services: /* @__PURE__ */ new Map(),
11036
- serviceTypeToString: /* @__PURE__ */ new Map(),
11037
- nextId: () => "id" + lastId++
11038
- };
11187
+ const options = yield* service(LanguageServicePluginOptions);
11188
+ const maybeNodes = yield* getAdjustedNode(sourceFile, position);
11189
+ if (!maybeNodes) return quickInfo2;
11190
+ const { layerNode, node } = maybeNodes;
11039
11191
  const layerInfoDisplayParts = yield* pipe(
11040
- processLayerGraphNode(graphCtx, layerNode, void 0),
11192
+ parseLayerGraph(sourceFile, layerNode),
11041
11193
  flatMap(
11042
- (rootNode) => gen(function* () {
11043
- yield* succeed(void 0);
11044
- const lines = [];
11045
- const appendInfo = (providesNode, type, kindText) => {
11046
- const typeString = typeChecker.typeToString(
11047
- type,
11048
- void 0,
11049
- ts.TypeFormatFlags.NoTruncation
11050
- );
11051
- const positions = providesNode.map((_) => {
11052
- const nodePosition = _.node.getStart(sourceFile, false);
11053
- const { character, line } = ts.getLineAndCharacterOfPosition(sourceFile, nodePosition);
11054
- const nodeText = _.node.getText().trim().replace(/\n/g, " ").substr(0, 50);
11055
- return "ln " + (line + 1) + " col " + character + " by `" + nodeText + "`";
11056
- });
11057
- lines.push("- " + typeString + " " + kindText + " at " + positions.join(", "));
11058
- };
11059
- for (const providesKey of rootNode.rout) {
11060
- const providesNode = findInnermostGraphEdge(rootNode, "rout", providesKey);
11061
- appendInfo(providesNode, graphCtx.services.get(providesKey), "provided");
11062
- }
11063
- if (lines.length > 0) lines.push("");
11064
- for (const requiresKey of rootNode.rin) {
11065
- const requiresNode = findInnermostGraphEdge(rootNode, "rin", requiresKey);
11066
- appendInfo(requiresNode, graphCtx.services.get(requiresKey), "required");
11067
- }
11068
- const mermaidUri = yield* option(generateMarmaidUri(rootNode, graphCtx));
11194
+ ({ mermaidCode, textualExplanation }) => gen(function* () {
11069
11195
  const linkParts = [];
11070
- if (isSome2(mermaidUri)) {
11196
+ if (!options.noExternal) {
11197
+ const mermaidUri = yield* generateMarmaidUri(mermaidCode);
11071
11198
  linkParts.push({ kind: "space", text: "\n" });
11072
11199
  linkParts.push({ kind: "link", text: "{@link " });
11073
- linkParts.push({ kind: "linkText", text: mermaidUri.value + " Show full Layer graph" });
11200
+ linkParts.push({ kind: "linkText", text: mermaidUri + " Show full Layer graph" });
11074
11201
  linkParts.push({ kind: "link", text: "}" });
11075
11202
  linkParts.push({ kind: "space", text: "\n" });
11076
11203
  }
11077
- if (lines.length === 0) return linkParts;
11204
+ if (textualExplanation.length === 0) return linkParts;
11078
11205
  return [
11079
11206
  {
11080
11207
  kind: "text",
11081
- text: "```\n/**\n" + lines.map((l) => " * " + l).join("\n") + "\n */\n```\n"
11208
+ text: "```\n/**\n" + textualExplanation.map((l) => " * " + l).join("\n") + "\n */\n```\n"
11082
11209
  },
11083
11210
  ...linkParts
11084
11211
  ];
@@ -13570,6 +13697,56 @@ var init = (modules) => {
13570
13697
  }
13571
13698
  return applicableRenameInfo;
13572
13699
  };
13700
+ const additionalProtocolHandlers = {
13701
+ "_effectGetLayerMermaid": (arg) => {
13702
+ const { character, line, path } = arg.arguments;
13703
+ const normalizedPath = modules.typescript.server.toNormalizedPath(path);
13704
+ const projectService = info.project.projectService;
13705
+ const scriptInfo = projectService.getScriptInfoForNormalizedPath(normalizedPath);
13706
+ if (scriptInfo) {
13707
+ const targetProject = scriptInfo.getDefaultProject();
13708
+ if (targetProject) {
13709
+ const program = targetProject.getLanguageService().getProgram();
13710
+ if (program) {
13711
+ const sourceFile = targetProject.getSourceFile(scriptInfo.path);
13712
+ if (sourceFile) {
13713
+ return pipe(
13714
+ effectApiGetLayerGraph(sourceFile, line, character),
13715
+ map3((response) => ({
13716
+ response: {
13717
+ success: true,
13718
+ ...response
13719
+ }
13720
+ })),
13721
+ runNano(program),
13722
+ getOrElse((e) => ({
13723
+ response: {
13724
+ success: false,
13725
+ error: e.message
13726
+ }
13727
+ }))
13728
+ );
13729
+ }
13730
+ }
13731
+ }
13732
+ }
13733
+ return {
13734
+ response: {
13735
+ success: false,
13736
+ error: "No source file found"
13737
+ }
13738
+ };
13739
+ }
13740
+ };
13741
+ if (info.session) {
13742
+ for (const [key, value] of Object.entries(additionalProtocolHandlers)) {
13743
+ try {
13744
+ info.session.addProtocolHandler(key, value);
13745
+ } catch (e) {
13746
+ info.project.log("[@effect/language-service] Skipped adding " + key + " protocol handler due to error: " + e);
13747
+ }
13748
+ }
13749
+ }
13573
13750
  return proxy;
13574
13751
  }
13575
13752
  return { create, onConfigurationChanged };