85 lines
3.2 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|
|
} |