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 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() .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().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; } } } }