Files
nub-lang/compiler/NubLang.LSP/WorkspaceManager.cs
2025-11-05 15:53:08 +01:00

68 lines
2.2 KiB
C#

using NubLang.Ast;
using NubLang.Diagnostics;
using NubLang.Modules;
using NubLang.Syntax;
namespace NubLang.LSP;
public class WorkspaceManager(DiagnosticsPublisher diagnosticsPublisher)
{
private record Unit(SyntaxTree SyntaxTree, DateTimeOffset FileTimestamp, List<Diagnostic> Diagnostics);
private readonly Tokenizer _tokenizer = new();
private readonly Parser _parser = new();
private readonly TypeChecker _typeChecker = new();
private string? _rootPath;
private readonly Dictionary<string, Unit> _units = [];
private readonly Dictionary<string, List<TopLevelNode>> _possiblyOutdatedTopLevelNodes = [];
private ModuleRepository _repository = new([]);
public void SetRootPath(string rootPath)
{
_rootPath = rootPath;
Update();
}
public void Update()
{
if (_rootPath == null) return;
var files = Directory.GetFiles(_rootPath, "*.nub", SearchOption.AllDirectories);
foreach (var file in files)
{
var lastUpdated = File.GetLastWriteTimeUtc(file);
var unit = _units.GetValueOrDefault(file);
if (unit == null || lastUpdated > unit.FileTimestamp)
{
_units[file] = Update(file, lastUpdated);
}
}
_repository = ModuleRepository.Create(_units.Select(x => x.Value.SyntaxTree).ToList());
foreach (var (file, unit) in _units)
{
var topLevelNodes = _typeChecker.Check(unit.SyntaxTree, _repository);
_possiblyOutdatedTopLevelNodes[file] = topLevelNodes;
diagnosticsPublisher.Publish(file, [..unit.Diagnostics, .._typeChecker.Diagnostics]);
}
}
private Unit Update(string file, DateTimeOffset lastUpdated)
{
var text = File.ReadAllText(file);
var tokens = _tokenizer.Tokenize(file, text);
var syntaxTree = _parser.Parse(tokens);
return new Unit(syntaxTree, lastUpdated, [.._tokenizer.Diagnostics, .._parser.Diagnostics]);
}
public List<TopLevelNode> GetTopLevelNodes(string path)
{
return _possiblyOutdatedTopLevelNodes.GetValueOrDefault(path, []);
}
public ModuleRepository GetModuleRepository()
{
return _repository;
}
}