using NubLang.Ast; using NubLang.Syntax; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using Range = OmniSharp.Extensions.LanguageServer.Protocol.Models.Range; namespace NubLang.LSP; public static class AstExtensions { public static Location ToLocation(this Node node) { if (node.Tokens.Count == 0) { return new Location(); } return new Location { Uri = node.Tokens.First().Span.FilePath, Range = new Range(node.Tokens.First().Span.Start.Line - 1, node.Tokens.First().Span.Start.Column - 1, node.Tokens.Last().Span.End.Line - 1, node.Tokens.Last().Span.End.Column - 1) }; } public static bool ContainsPosition(this Node node, int line, int character) { if (node.Tokens.Count == 0) { return false; } var start = node.Tokens.First().Span.Start; var end = node.Tokens.Last().Span.End; var startLine = start.Line - 1; var startChar = start.Column - 1; var endLine = end.Line - 1; var endChar = end.Column - 1; if (line < startLine || line > endLine) return false; if (line > startLine && line < endLine) return true; if (startLine == endLine) { return character >= startChar && character <= endChar; } if (line == startLine) { return character >= startChar; } if (line == endLine) { return character <= endChar; } 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.DescendantsAndSelf()) .Where(n => n.ContainsPosition(line, character)) .OrderBy(n => n.Tokens.First().Span.Start.Line) .ThenBy(n => n.Tokens.First().Span.Start.Column) .LastOrDefault(); } }