Jump to definition
This commit is contained in:
@@ -41,6 +41,32 @@ public static class AstExtensions
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static FuncNode? FunctionAtPosition(this CompilationUnit compilationUnit, int line, int character)
|
||||||
|
{
|
||||||
|
return compilationUnit
|
||||||
|
.Functions
|
||||||
|
.FirstOrDefault(x => x.ContainsPosition(line, character));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Node? DeepestNodeAtPosition(this CompilationUnit compilationUnit, int line, int character)
|
||||||
|
{
|
||||||
|
return compilationUnit.Functions
|
||||||
|
.SelectMany(x => x.EnumerateDescendantsAndSelf())
|
||||||
|
.Where(n => n.ContainsPosition(line, character))
|
||||||
|
.OrderBy(n => n.Tokens.First().Span.Start.Line)
|
||||||
|
.ThenBy(n => n.Tokens.First().Span.Start.Column)
|
||||||
|
.LastOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Node? DeepestNodeAtPosition(this Node node, int line, int character)
|
||||||
|
{
|
||||||
|
return node.EnumerateDescendantsAndSelf()
|
||||||
|
.Where(n => n.ContainsPosition(line, character))
|
||||||
|
.OrderBy(n => n.Tokens.First().Span.Start.Line)
|
||||||
|
.ThenBy(n => n.Tokens.First().Span.Start.Column)
|
||||||
|
.LastOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
public static IEnumerable<Node> EnumerateDescendantsAndSelf(this Node node)
|
public static IEnumerable<Node> EnumerateDescendantsAndSelf(this Node node)
|
||||||
{
|
{
|
||||||
yield return node;
|
yield return node;
|
||||||
|
|||||||
97
compiler/NubLang.LSP/DefinitionHandler.cs
Normal file
97
compiler/NubLang.LSP/DefinitionHandler.cs
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
using NubLang.Ast;
|
||||||
|
using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities;
|
||||||
|
using OmniSharp.Extensions.LanguageServer.Protocol.Document;
|
||||||
|
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
|
||||||
|
using Range = OmniSharp.Extensions.LanguageServer.Protocol.Models.Range;
|
||||||
|
|
||||||
|
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 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)
|
||||||
|
{
|
||||||
|
if (parameter.Tokens.Count == 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new LocationOrLocationLinks(new Location
|
||||||
|
{
|
||||||
|
Uri = parameter.Tokens.First().Span.FilePath,
|
||||||
|
Range = new Range(parameter.Tokens.First().Span.Start.Line - 1, parameter.Tokens.First().Span.Start.Column - 1, parameter.Tokens.Last().Span.End.Line - 1, parameter.Tokens.Last().Span.End.Column - 1)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var variable = function?.Body?
|
||||||
|
.EnumerateDescendantsAndSelf()
|
||||||
|
.OfType<VariableDeclarationNode>()
|
||||||
|
.FirstOrDefault(x => x.Name == variableIdentifierNode.Name);
|
||||||
|
|
||||||
|
if (variable != null)
|
||||||
|
{
|
||||||
|
if (variable.Tokens.Count == 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new LocationOrLocationLinks(new Location
|
||||||
|
{
|
||||||
|
Uri = variable.Tokens.First().Span.FilePath,
|
||||||
|
Range = new Range(variable.Tokens.First().Span.Start.Line - 1, variable.Tokens.First().Span.Start.Column - 1, variable.Tokens.Last().Span.End.Line - 1, variable.Tokens.Last().Span.End.Column - 1)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
case FuncIdentifierNode funcIdentifierNode:
|
||||||
|
{
|
||||||
|
var functionBody = compilationUnit.ImportedFunctions.FirstOrDefault(x => x.Module == funcIdentifierNode.Module && x.Name == funcIdentifierNode.Name);
|
||||||
|
if (functionBody == null || functionBody.Tokens.Count == 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new LocationOrLocationLinks(new Location
|
||||||
|
{
|
||||||
|
Uri = functionBody.Tokens.First().Span.FilePath,
|
||||||
|
Range = new Range(functionBody.Tokens.First().Span.Start.Line - 1, functionBody.Tokens.First().Span.Start.Column - 1, functionBody.Tokens.Last().Span.End.Line - 1, functionBody.Tokens.Last().Span.End.Column - 1)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,12 +32,7 @@ internal class HoverHandler(WorkspaceManager workspaceManager) : HoverHandlerBas
|
|||||||
var line = request.Position.Line;
|
var line = request.Position.Line;
|
||||||
var character = request.Position.Character;
|
var character = request.Position.Character;
|
||||||
|
|
||||||
var hoveredNode = compilationUnit.Functions
|
var hoveredNode = compilationUnit.DeepestNodeAtPosition(line, character);
|
||||||
.SelectMany(x => x.EnumerateDescendantsAndSelf())
|
|
||||||
.Where(n => n.ContainsPosition(line, character))
|
|
||||||
.OrderBy(n => n.Tokens.First().Span.Start.Line)
|
|
||||||
.ThenBy(n => n.Tokens.First().Span.Start.Column)
|
|
||||||
.LastOrDefault();
|
|
||||||
|
|
||||||
if (hoveredNode == null)
|
if (hoveredNode == null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ var server = await LanguageServer.From(options => options
|
|||||||
.WithHandler<TextDocumentSyncHandler>()
|
.WithHandler<TextDocumentSyncHandler>()
|
||||||
.WithHandler<HoverHandler>()
|
.WithHandler<HoverHandler>()
|
||||||
.WithHandler<CompletionHandler>()
|
.WithHandler<CompletionHandler>()
|
||||||
|
.WithHandler<DefinitionHandler>()
|
||||||
.OnInitialize((server, request, ct) =>
|
.OnInitialize((server, request, ct) =>
|
||||||
{
|
{
|
||||||
var workspaceManager = server.GetRequiredService<WorkspaceManager>();
|
var workspaceManager = server.GetRequiredService<WorkspaceManager>();
|
||||||
|
|||||||
Reference in New Issue
Block a user