...
This commit is contained in:
@@ -2,100 +2,67 @@ using NubLang.Ast;
|
||||
using NubLang.Diagnostics;
|
||||
using NubLang.Modules;
|
||||
using NubLang.Syntax;
|
||||
using OmniSharp.Extensions.LanguageServer.Protocol;
|
||||
|
||||
namespace NubLang.LSP;
|
||||
|
||||
public class WorkspaceManager(DiagnosticsPublisher diagnosticsPublisher)
|
||||
{
|
||||
private readonly Dictionary<string, SyntaxTree> _syntaxTrees = new();
|
||||
private readonly Dictionary<string, List<TopLevelNode>> _compilationUnits = new();
|
||||
private ModuleRepository? _repository;
|
||||
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 Init(string rootPath)
|
||||
{
|
||||
var files = Directory.GetFiles(rootPath, "*.nub", SearchOption.AllDirectories);
|
||||
foreach (var path in files)
|
||||
_rootPath = rootPath;
|
||||
Update();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (_rootPath == null) return;
|
||||
var files = Directory.GetFiles(_rootPath, "*.nub", SearchOption.AllDirectories);
|
||||
foreach (var file in files)
|
||||
{
|
||||
var text = File.ReadAllText(path);
|
||||
var tokenizer = new Tokenizer();
|
||||
|
||||
tokenizer.Tokenize(path, text);
|
||||
diagnosticsPublisher.Publish(path, tokenizer.Diagnostics);
|
||||
|
||||
var parser = new Parser();
|
||||
var parseResult = parser.Parse(tokenizer.Tokens);
|
||||
diagnosticsPublisher.Publish(path, parser.Diagnostics);
|
||||
|
||||
_syntaxTrees[path] = parseResult;
|
||||
}
|
||||
|
||||
ModuleRepository repository;
|
||||
|
||||
foreach (var (fsPath, syntaxTree) in _syntaxTrees)
|
||||
{
|
||||
try
|
||||
var lastUpdated = File.GetLastWriteTimeUtc(file);
|
||||
var unit = _units.GetValueOrDefault(file);
|
||||
if (unit == null || lastUpdated > unit.FileTimestamp)
|
||||
{
|
||||
repository = ModuleRepository.Create(_syntaxTrees.Select(x => x.Value).ToList());
|
||||
}
|
||||
catch (CompileException e)
|
||||
{
|
||||
return;
|
||||
_units[file] = Update(file, lastUpdated);
|
||||
}
|
||||
}
|
||||
|
||||
var typeChecker = new TypeChecker();
|
||||
var result = typeChecker.Check(syntaxTree, repository);
|
||||
diagnosticsPublisher.Publish(fsPath, typeChecker.Diagnostics);
|
||||
_compilationUnits[fsPath] = result;
|
||||
_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]);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateFile(DocumentUri path)
|
||||
private Unit Update(string file, DateTimeOffset lastUpdated)
|
||||
{
|
||||
var fsPath = path.GetFileSystemPath();
|
||||
var text = File.ReadAllText(file);
|
||||
var tokens = _tokenizer.Tokenize(file, text);
|
||||
var syntaxTree = _parser.Parse(tokens);
|
||||
|
||||
var text = File.ReadAllText(fsPath);
|
||||
var tokenizer = new Tokenizer();
|
||||
tokenizer.Tokenize(fsPath, text);
|
||||
diagnosticsPublisher.Publish(path, tokenizer.Diagnostics);
|
||||
|
||||
var parser = new Parser();
|
||||
var syntaxTree = parser.Parse(tokenizer.Tokens);
|
||||
diagnosticsPublisher.Publish(path, parser.Diagnostics);
|
||||
_syntaxTrees[fsPath] = syntaxTree;
|
||||
|
||||
ModuleRepository repository;
|
||||
|
||||
try
|
||||
{
|
||||
repository = ModuleRepository.Create(_syntaxTrees.Select(x => x.Value).ToList());
|
||||
}
|
||||
catch (CompileException e)
|
||||
{
|
||||
diagnosticsPublisher.Publish(path, [e.Diagnostic]);
|
||||
return;
|
||||
}
|
||||
|
||||
var typeChecker = new TypeChecker();
|
||||
var result = typeChecker.Check(syntaxTree, repository);
|
||||
diagnosticsPublisher.Publish(fsPath, typeChecker.Diagnostics);
|
||||
_compilationUnits[fsPath] = result;
|
||||
return new Unit(syntaxTree, lastUpdated, [.._tokenizer.Diagnostics, .._parser.Diagnostics]);
|
||||
}
|
||||
|
||||
public List<TopLevelNode>? GetCompilationUnit(DocumentUri path)
|
||||
public List<TopLevelNode> GetTopLevelNodes(string path)
|
||||
{
|
||||
return _compilationUnits.GetValueOrDefault(path.GetFileSystemPath());
|
||||
return _possiblyOutdatedTopLevelNodes.GetValueOrDefault(path, []);
|
||||
}
|
||||
|
||||
public ModuleRepository? GetModuleRepository()
|
||||
public ModuleRepository GetModuleRepository()
|
||||
{
|
||||
try
|
||||
{
|
||||
return ModuleRepository.Create(_syntaxTrees.Select(x => x.Value).ToList());
|
||||
}
|
||||
catch (CompileException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return _repository;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user