diff --git a/compiler/Compiler.sln b/compiler/Compiler.sln index 480156a..292d374 100644 --- a/compiler/Compiler.sln +++ b/compiler/Compiler.sln @@ -4,8 +4,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NubLang", "NubLang\NubLang. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NubLang.CLI", "NubLang.CLI\NubLang.CLI.csproj", "{A22F17ED-FA17-45AB-92BA-CD02C28B3524}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NubLang.LSP", "NubLang.LSP\NubLang.LSP.csproj", "{07968F84-0C2E-4D2E-8905-DC8A6140B4C0}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -20,9 +18,5 @@ Global {A22F17ED-FA17-45AB-92BA-CD02C28B3524}.Debug|Any CPU.Build.0 = Debug|Any CPU {A22F17ED-FA17-45AB-92BA-CD02C28B3524}.Release|Any CPU.ActiveCfg = Release|Any CPU {A22F17ED-FA17-45AB-92BA-CD02C28B3524}.Release|Any CPU.Build.0 = Release|Any CPU - {07968F84-0C2E-4D2E-8905-DC8A6140B4C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {07968F84-0C2E-4D2E-8905-DC8A6140B4C0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {07968F84-0C2E-4D2E-8905-DC8A6140B4C0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {07968F84-0C2E-4D2E-8905-DC8A6140B4C0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/compiler/NubLang.LSP/AstExtensions.cs b/compiler/NubLang.LSP/AstExtensions.cs deleted file mode 100644 index e0b2477..0000000 --- a/compiler/NubLang.LSP/AstExtensions.cs +++ /dev/null @@ -1,77 +0,0 @@ -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(); - } -} \ No newline at end of file diff --git a/compiler/NubLang.LSP/CompletionHandler.cs b/compiler/NubLang.LSP/CompletionHandler.cs deleted file mode 100644 index 8155328..0000000 --- a/compiler/NubLang.LSP/CompletionHandler.cs +++ /dev/null @@ -1,180 +0,0 @@ -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 CompletionHandler(WorkspaceManager workspaceManager) : CompletionHandlerBase -{ - private readonly CompletionItem[] _definitionSnippets = - [ - new() - { - Kind = CompletionItemKind.Keyword, - Label = "func", - InsertTextFormat = InsertTextFormat.Snippet, - InsertText = "func ${1:name}(${2:params})\n{\n $0\n}", - }, - new() - { - Kind = CompletionItemKind.Keyword, - Label = "struct", - InsertTextFormat = InsertTextFormat.Snippet, - InsertText = "struct ${1:name}\n{\n $0\n}", - }, - new() - { - Kind = CompletionItemKind.Keyword, - Label = "module", - InsertTextFormat = InsertTextFormat.Snippet, - InsertText = "module \"$0\"", - }, - new() - { - Kind = CompletionItemKind.Keyword, - Label = "import", - InsertTextFormat = InsertTextFormat.Snippet, - InsertText = "import \"$0\"", - } - ]; - - private readonly CompletionItem[] _statementSnippets = - [ - new() - { - Kind = CompletionItemKind.Keyword, - Label = "let", - InsertTextFormat = InsertTextFormat.Snippet, - InsertText = "let ${1:name} = $0", - }, - new() - { - Kind = CompletionItemKind.Keyword, - Label = "if", - InsertTextFormat = InsertTextFormat.Snippet, - InsertText = "if ${1:condition}\n{\n $0\n}", - }, - new() - { - Kind = CompletionItemKind.Keyword, - Label = "else if", - InsertTextFormat = InsertTextFormat.Snippet, - InsertText = "else if ${1:condition}\n{\n $0\n}", - }, - new() - { - Kind = CompletionItemKind.Keyword, - Label = "else", - InsertTextFormat = InsertTextFormat.Snippet, - InsertText = "else\n{\n $0\n}", - }, - new() - { - Kind = CompletionItemKind.Keyword, - Label = "while", - InsertTextFormat = InsertTextFormat.Snippet, - InsertText = "while ${1:condition}\n{\n $0\n}", - }, - new() - { - Kind = CompletionItemKind.Keyword, - Label = "for", - InsertTextFormat = InsertTextFormat.Snippet, - InsertText = "for ${1:name}, ${2:index} in ${3:array}\n{\n $0\n}", - }, - new() - { - Kind = CompletionItemKind.Keyword, - Label = "return", - InsertTextFormat = InsertTextFormat.Snippet, - InsertText = "return $0", - }, - new() - { - Kind = CompletionItemKind.Keyword, - Label = "defer", - InsertTextFormat = InsertTextFormat.Snippet, - InsertText = "defer $0", - } - ]; - - protected override CompletionRegistrationOptions CreateRegistrationOptions(CompletionCapability capability, ClientCapabilities clientCapabilities) - { - return new CompletionRegistrationOptions(); - } - - public override Task Handle(CompletionParams request, CancellationToken cancellationToken) - { - return Task.FromResult(HandleSync(request, cancellationToken)); - } - - private CompletionList HandleSync(CompletionParams request, CancellationToken cancellationToken) - { - var completions = new List(); - var position = request.Position; - - var uri = request.TextDocument.Uri; - var compilationUnit = workspaceManager.GetCompilationUnit(uri); - if (compilationUnit != null) - { - var function = compilationUnit.Functions.FirstOrDefault(x => x.Body != null && x.Body.ContainsPosition(position.Line, position.Character)); - if (function != null) - { - completions.AddRange(_statementSnippets); - - foreach (var prototype in compilationUnit.ImportedFunctions) - { - var parameterStrings = new List(); - foreach (var (index, parameter) in prototype.Parameters.Index()) - { - parameterStrings.AddRange($"${{{index + 1}:{parameter.Name}}}"); - } - - completions.Add(new CompletionItem - { - Kind = CompletionItemKind.Function, - Label = $"{prototype.Module}::{prototype.Name}", - InsertTextFormat = InsertTextFormat.Snippet, - InsertText = $"{prototype.Module}::{prototype.Name}({string.Join(", ", parameterStrings)})", - }); - } - - foreach (var parameter in function.Prototype.Parameters) - { - completions.Add(new CompletionItem - { - Kind = CompletionItemKind.Variable, - Label = parameter.Name, - InsertText = parameter.Name, - }); - } - - var variables = function.Body! - .Descendants() - .OfType(); - - foreach (var variable in variables) - { - completions.Add(new CompletionItem - { - Kind = CompletionItemKind.Variable, - Label = variable.Name, - InsertText = variable.Name, - }); - } - } - else - { - completions.AddRange(_definitionSnippets); - } - } - - return new CompletionList(completions, false); - } - - public override Task Handle(CompletionItem request, CancellationToken cancellationToken) - { - return Task.FromResult(new CompletionItem()); - } -} \ No newline at end of file diff --git a/compiler/NubLang.LSP/DefinitionHandler.cs b/compiler/NubLang.LSP/DefinitionHandler.cs deleted file mode 100644 index d354e9d..0000000 --- a/compiler/NubLang.LSP/DefinitionHandler.cs +++ /dev/null @@ -1,74 +0,0 @@ -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; - } - } - } -} \ No newline at end of file diff --git a/compiler/NubLang.LSP/DiagnosticsPublisher.cs b/compiler/NubLang.LSP/DiagnosticsPublisher.cs deleted file mode 100644 index 7364396..0000000 --- a/compiler/NubLang.LSP/DiagnosticsPublisher.cs +++ /dev/null @@ -1,44 +0,0 @@ -using OmniSharp.Extensions.LanguageServer.Protocol; -using OmniSharp.Extensions.LanguageServer.Protocol.Document; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Server; -using Range = OmniSharp.Extensions.LanguageServer.Protocol.Models.Range; - -namespace NubLang.LSP; - -public class DiagnosticsPublisher -{ - private readonly ILanguageServerFacade _server; - - public DiagnosticsPublisher(ILanguageServerFacade server) - { - _server = server; - } - - public void Publish(DocumentUri uri, IEnumerable diagnostics) - { - _server.TextDocument.PublishDiagnostics(new PublishDiagnosticsParams - { - Uri = uri, - Diagnostics = new Container(diagnostics.Select(MapDiagnostic)) - }); - } - - private static Diagnostic MapDiagnostic(Diagnostics.Diagnostic nubDiagnostic) - { - return new Diagnostic - { - Severity = nubDiagnostic.Severity switch - { - Diagnostics.DiagnosticSeverity.Info => DiagnosticSeverity.Information, - Diagnostics.DiagnosticSeverity.Warning => DiagnosticSeverity.Warning, - Diagnostics.DiagnosticSeverity.Error => DiagnosticSeverity.Error, - _ => null - }, - Message = $"{nubDiagnostic.Message}\n{(nubDiagnostic.Help == null ? "" : $"help: {nubDiagnostic.Help}")}", - Range = nubDiagnostic.Span.HasValue - ? new Range(nubDiagnostic.Span.Value.Start.Line - 1, nubDiagnostic.Span.Value.Start.Column - 1, nubDiagnostic.Span.Value.End.Line - 1, nubDiagnostic.Span.Value.End.Column - 1) - : new Range(), - }; - } -} \ No newline at end of file diff --git a/compiler/NubLang.LSP/HoverHandler.cs b/compiler/NubLang.LSP/HoverHandler.cs deleted file mode 100644 index f90e6c0..0000000 --- a/compiler/NubLang.LSP/HoverHandler.cs +++ /dev/null @@ -1,142 +0,0 @@ -using System.Globalization; -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 HoverHandler(WorkspaceManager workspaceManager) : HoverHandlerBase -{ - protected override HoverRegistrationOptions CreateRegistrationOptions(HoverCapability capability, ClientCapabilities clientCapabilities) - { - return new HoverRegistrationOptions - { - DocumentSelector = TextDocumentSelector.ForLanguage("nub") - }; - } - - public override Task Handle(HoverParams request, CancellationToken cancellationToken) - { - return Task.FromResult(HandleSync(request, cancellationToken)); - } - - private Hover? HandleSync(HoverParams request, CancellationToken cancellationToken) - { - var compilationUnit = workspaceManager.GetCompilationUnit(request.TextDocument.Uri); - if (compilationUnit == null) - { - return null; - } - - var line = request.Position.Line; - var character = request.Position.Character; - - var hoveredNode = compilationUnit.DeepestNodeAtPosition(line, character); - - if (hoveredNode == null) - { - return null; - } - - var message = CreateMessage(hoveredNode, compilationUnit); - if (message == null) - { - return null; - } - - return new Hover - { - Contents = new MarkedStringsOrMarkupContent(new MarkupContent - { - Value = message, - Kind = MarkupKind.Markdown, - }) - }; - } - - private static string? CreateMessage(Node hoveredNode, CompilationUnit compilationUnit) - { - return hoveredNode switch - { - FuncNode funcNode => CreateFuncPrototypeMessage(funcNode.Prototype), - FuncPrototypeNode funcPrototypeNode => CreateFuncPrototypeMessage(funcPrototypeNode), - FuncIdentifierNode funcIdentifierNode => CreateFuncIdentifierMessage(funcIdentifierNode, compilationUnit), - FuncParameterNode funcParameterNode => CreateTypeNameMessage("Function parameter", funcParameterNode.Name, funcParameterNode.Type), - VariableIdentifierNode variableIdentifierNode => CreateTypeNameMessage("Variable", variableIdentifierNode.Name, variableIdentifierNode.Type), - VariableDeclarationNode variableDeclarationNode => CreateTypeNameMessage("Variable declaration", variableDeclarationNode.Name, variableDeclarationNode.Type), - StructFieldAccessNode structFieldAccessNode => CreateTypeNameMessage("Struct field", $"{structFieldAccessNode.Target.Type}.{structFieldAccessNode.Field}", structFieldAccessNode.Type), - CStringLiteralNode cStringLiteralNode => CreateLiteralMessage(cStringLiteralNode.Type, '"' + cStringLiteralNode.Value + '"'), - StringLiteralNode stringLiteralNode => CreateLiteralMessage(stringLiteralNode.Type, '"' + stringLiteralNode.Value + '"'), - BoolLiteralNode boolLiteralNode => CreateLiteralMessage(boolLiteralNode.Type, boolLiteralNode.Value.ToString()), - Float32LiteralNode float32LiteralNode => CreateLiteralMessage(float32LiteralNode.Type, float32LiteralNode.Value.ToString(CultureInfo.InvariantCulture)), - Float64LiteralNode float64LiteralNode => CreateLiteralMessage(float64LiteralNode.Type, float64LiteralNode.Value.ToString(CultureInfo.InvariantCulture)), - I8LiteralNode i8LiteralNode => CreateLiteralMessage(i8LiteralNode.Type, i8LiteralNode.Value.ToString()), - I16LiteralNode i16LiteralNode => CreateLiteralMessage(i16LiteralNode.Type, i16LiteralNode.Value.ToString()), - I32LiteralNode i32LiteralNode => CreateLiteralMessage(i32LiteralNode.Type, i32LiteralNode.Value.ToString()), - I64LiteralNode i64LiteralNode => CreateLiteralMessage(i64LiteralNode.Type, i64LiteralNode.Value.ToString()), - U8LiteralNode u8LiteralNode => CreateLiteralMessage(u8LiteralNode.Type, u8LiteralNode.Value.ToString()), - U16LiteralNode u16LiteralNode => CreateLiteralMessage(u16LiteralNode.Type, u16LiteralNode.Value.ToString()), - U32LiteralNode u32LiteralNode => CreateLiteralMessage(u32LiteralNode.Type, u32LiteralNode.Value.ToString()), - U64LiteralNode u64LiteralNode => CreateLiteralMessage(u64LiteralNode.Type, u64LiteralNode.Value.ToString()), - // Expressions can have a generic fallback showing the resulting type - ExpressionNode expressionNode => $""" - **Expression** `{expressionNode.GetType().Name}` - ```nub - {expressionNode.Type} - ``` - """, - BlockNode => null, - _ => hoveredNode.GetType().Name - }; - } - - private static string CreateLiteralMessage(NubType type, string value) - { - return $""" - **Literal** `{type}` - ```nub - {value}: {type} - ``` - """; - } - - private static string CreateTypeNameMessage(string description, string name, NubType type) - { - return $""" - **{description}** `{name}` - ```nub - {name}: {type} - ``` - """; - } - - private static string CreateFuncIdentifierMessage(FuncIdentifierNode funcIdentifierNode, CompilationUnit compilationUnit) - { - var func = compilationUnit.ImportedFunctions.FirstOrDefault(x => x.Module == funcIdentifierNode.Module && x.Name == funcIdentifierNode.Name); - if (func == null) - { - return $""" - **Function** `{funcIdentifierNode.Module}::{funcIdentifierNode.Name}` - ```nub - // Declaration not found - ``` - """; - } - - return CreateFuncPrototypeMessage(func); - } - - private static string CreateFuncPrototypeMessage(FuncPrototypeNode funcPrototypeNode) - { - var parameterText = string.Join(", ", funcPrototypeNode.Parameters.Select(x => $"{x.Name}: {x.Type}")); - var externText = funcPrototypeNode.ExternSymbol != null ? $"extern \"{funcPrototypeNode.ExternSymbol}\" " : ""; - - return $""" - **Function** `{funcPrototypeNode.Module}::{funcPrototypeNode.Name}` - ```nub - {externText}func {funcPrototypeNode.Module}::{funcPrototypeNode.Name}({parameterText}): {funcPrototypeNode.ReturnType} - ``` - """; - } -} \ No newline at end of file diff --git a/compiler/NubLang.LSP/NubLang.LSP.csproj b/compiler/NubLang.LSP/NubLang.LSP.csproj deleted file mode 100644 index 720f388..0000000 --- a/compiler/NubLang.LSP/NubLang.LSP.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - nublsp - Exe - net9.0 - enable - enable - true - true - - - - - - - - - - - diff --git a/compiler/NubLang.LSP/Program.cs b/compiler/NubLang.LSP/Program.cs deleted file mode 100644 index 095630f..0000000 --- a/compiler/NubLang.LSP/Program.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using NubLang.LSP; -using OmniSharp.Extensions.LanguageServer.Server; - -var server = await LanguageServer.From(options => options - .WithInput(Console.OpenStandardInput()) - .WithOutput(Console.OpenStandardOutput()) - .WithServices(services => - { - services.AddSingleton(); - services.AddSingleton(); - }) - .ConfigureLogging(x => x - .AddLanguageProtocolLogging() - .SetMinimumLevel(LogLevel.Debug)) - .WithHandler() - .WithHandler() - .WithHandler() - .WithHandler() - .OnInitialize((server, request, ct) => - { - var workspaceManager = server.GetRequiredService(); - - if (request.RootPath != null) - { - workspaceManager.Init(request.RootPath); - } - - return Task.CompletedTask; - }) -); - -await server.WaitForExit; \ No newline at end of file diff --git a/compiler/NubLang.LSP/TextDocumentSyncHandler.cs b/compiler/NubLang.LSP/TextDocumentSyncHandler.cs deleted file mode 100644 index e29aa44..0000000 --- a/compiler/NubLang.LSP/TextDocumentSyncHandler.cs +++ /dev/null @@ -1,44 +0,0 @@ -using MediatR; -using OmniSharp.Extensions.LanguageServer.Protocol; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Document; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace NubLang.LSP; - -internal class TextDocumentSyncHandler(WorkspaceManager workspaceManager) : TextDocumentSyncHandlerBase -{ - public override TextDocumentAttributes GetTextDocumentAttributes(DocumentUri uri) - { - return new TextDocumentAttributes(uri, "nub"); - } - - public override Task Handle(DidOpenTextDocumentParams request, CancellationToken cancellationToken) - { - workspaceManager.UpdateFile(request.TextDocument.Uri.GetFileSystemPath()); - return Unit.Task; - } - - public override Task Handle(DidChangeTextDocumentParams request, CancellationToken cancellationToken) - { - workspaceManager.UpdateFile(request.TextDocument.Uri.GetFileSystemPath()); - return Unit.Task; - } - - public override Task Handle(DidSaveTextDocumentParams request, CancellationToken cancellationToken) - { - workspaceManager.UpdateFile(request.TextDocument.Uri.GetFileSystemPath()); - return Unit.Task; - } - - public override Task Handle(DidCloseTextDocumentParams request, CancellationToken cancellationToken) - { - workspaceManager.UpdateFile(request.TextDocument.Uri.GetFileSystemPath()); - return Unit.Task; - } - - protected override TextDocumentSyncRegistrationOptions CreateRegistrationOptions(TextSynchronizationCapability capability, ClientCapabilities clientCapabilities) - { - return new TextDocumentSyncRegistrationOptions(); - } -} \ No newline at end of file diff --git a/compiler/NubLang.LSP/WorkspaceManager.cs b/compiler/NubLang.LSP/WorkspaceManager.cs deleted file mode 100644 index a897e13..0000000 --- a/compiler/NubLang.LSP/WorkspaceManager.cs +++ /dev/null @@ -1,74 +0,0 @@ -using NubLang.Ast; -using NubLang.Syntax; -using OmniSharp.Extensions.LanguageServer.Protocol; - -namespace NubLang.LSP; - -public class WorkspaceManager(DiagnosticsPublisher diagnosticsPublisher) -{ - private readonly Dictionary _syntaxTrees = new(); - private readonly Dictionary _compilationUnits = new(); - - public void Init(string rootPath) - { - var files = Directory.GetFiles(rootPath, "*.nub", SearchOption.AllDirectories); - foreach (var path in files) - { - var text = File.ReadAllText(path); - var tokenizer = new Tokenizer(path, text); - - tokenizer.Tokenize(); - diagnosticsPublisher.Publish(path, tokenizer.Diagnostics); - - var parser = new Parser(); - var parseResult = parser.Parse(tokenizer.Tokens); - diagnosticsPublisher.Publish(path, parser.Diagnostics); - - _syntaxTrees[path] = parseResult; - } - - foreach (var (fsPath, syntaxTree) in _syntaxTrees) - { - var modules = Module.Collect(_syntaxTrees.Select(x => x.Value).ToList()); - - var typeChecker = new TypeChecker(syntaxTree, modules); - var result = typeChecker.Check(); - diagnosticsPublisher.Publish(fsPath, typeChecker.Diagnostics); - _compilationUnits[fsPath] = result; - } - } - - public void UpdateFile(DocumentUri path) - { - var fsPath = path.GetFileSystemPath(); - - var text = File.ReadAllText(fsPath); - var tokenizer = new Tokenizer(fsPath, text); - tokenizer.Tokenize(); - diagnosticsPublisher.Publish(path, tokenizer.Diagnostics); - - var parser = new Parser(); - var syntaxTree = parser.Parse(tokenizer.Tokens); - diagnosticsPublisher.Publish(path, parser.Diagnostics); - _syntaxTrees[fsPath] = syntaxTree; - - var modules = Module.Collect(_syntaxTrees.Select(x => x.Value).ToList()); - - var typeChecker = new TypeChecker(syntaxTree, modules); - var result = typeChecker.Check(); - diagnosticsPublisher.Publish(fsPath, typeChecker.Diagnostics); - _compilationUnits[fsPath] = result; - } - - public void RemoveFile(DocumentUri path) - { - var fsPath = path.GetFileSystemPath(); - _syntaxTrees.Remove(fsPath); - _compilationUnits.Remove(fsPath); - } - - public CompilationUnit? GetCompilationUnit(DocumentUri path) - { - return _compilationUnits.GetValueOrDefault(path.GetFileSystemPath()); - } -} \ No newline at end of file