Files
nub-lang/compiler/NubLang.LSP/DefinitionHandler.cs
nub31 085f7a1a6a ...
2025-11-03 12:52:17 +01:00

85 lines
3.2 KiB
C#

using NubLang.Ast;
using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities;
using OmniSharp.Extensions.LanguageServer.Protocol.Document;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
namespace NubLang.LSP;
internal class DefinitionHandler(WorkspaceManager workspaceManager) : DefinitionHandlerBase
{
protected override DefinitionRegistrationOptions CreateRegistrationOptions(DefinitionCapability capability, ClientCapabilities clientCapabilities)
{
return new DefinitionRegistrationOptions();
}
public override Task<LocationOrLocationLinks?> Handle(DefinitionParams request, CancellationToken cancellationToken)
{
return Task.FromResult(HandleSync(request, cancellationToken));
}
private LocationOrLocationLinks? HandleSync(DefinitionParams request, CancellationToken cancellationToken)
{
var uri = request.TextDocument.Uri;
var topLevelNodes = workspaceManager.GetTopLevelNodes(uri.GetFileSystemPath());
var line = request.Position.Line;
var character = request.Position.Character;
var node = topLevelNodes.DeepestNodeAtPosition(line, character);
switch (node)
{
case VariableIdentifierNode variableIdentifierNode:
{
var funcNode = topLevelNodes.FunctionAtPosition(line, character);
var parameter = funcNode?.Prototype.Parameters.FirstOrDefault(x => x.NameToken.Value == variableIdentifierNode.NameToken.Value);
if (parameter != null)
{
return new LocationOrLocationLinks(parameter.NameToken.ToLocation());
}
var variable = funcNode?.Body?
.Descendants()
.OfType<VariableDeclarationNode>()
.FirstOrDefault(x => x.NameToken.Value == variableIdentifierNode.NameToken.Value);
if (variable != null)
{
return new LocationOrLocationLinks(variable.NameToken.ToLocation());
}
return null;
}
case LocalFuncIdentifierNode localFuncIdentifierNode:
{
var funcNode = topLevelNodes.OfType<FuncNode>().FirstOrDefault(x => x.NameToken.Value == localFuncIdentifierNode.NameToken.Value);
if (funcNode != null)
{
return new LocationOrLocationLinks(funcNode.NameToken.ToLocation());
}
return null;
}
case ModuleFuncIdentifierNode localFuncIdentifierNode:
{
var repository = workspaceManager.GetModuleRepository();
if (!repository.TryGet(localFuncIdentifierNode.ModuleToken, out var module))
{
return null;
}
if (module.TryResolveFunc(localFuncIdentifierNode.NameToken, out var func, out _))
{
return new LocationOrLocationLinks(func.NameToken.ToLocation());
}
return null;
}
default:
{
return null;
}
}
}
}