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 compilationUnit = workspaceManager.GetCompilationUnit(uri); if (compilationUnit == null) { return null; } var line = request.Position.Line; var character = request.Position.Character; var node = compilationUnit.DeepestNodeAtPosition(line, character); switch (node) { case VariableIdentifierNode variableIdentifierNode: { var function = compilationUnit.FunctionAtPosition(line, character); var parameter = function?.Prototype.Parameters.FirstOrDefault(x => x.Name == variableIdentifierNode.Name); if (parameter != null) { return new LocationOrLocationLinks(parameter.ToLocation()); } var variable = function?.Body? .Descendants() .OfType() .FirstOrDefault(x => x.Name == variableIdentifierNode.Name); if (variable != null) { return new LocationOrLocationLinks(variable.ToLocation()); } return null; } case FuncIdentifierNode funcIdentifierNode: { var prototype = compilationUnit.ImportedFunctions.FirstOrDefault(x => x.Module == funcIdentifierNode.Module && x.Name == funcIdentifierNode.Name); if (prototype != null) { return new LocationOrLocationLinks(prototype.ToLocation()); } return null; } default: { return null; } } } }